Home | History | Annotate | Download | only in nfc
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.nfc;
     18 
     19 import com.android.nfc.DeviceHost.DeviceHostListener;
     20 import com.android.nfc.DeviceHost.LlcpConnectionlessSocket;
     21 import com.android.nfc.DeviceHost.LlcpServerSocket;
     22 import com.android.nfc.DeviceHost.LlcpSocket;
     23 import com.android.nfc.DeviceHost.NfcDepEndpoint;
     24 import com.android.nfc.DeviceHost.TagEndpoint;
     25 import com.android.nfc.handover.HandoverManager;
     26 import com.android.nfc.dhimpl.NativeNfcManager;
     27 import com.android.nfc.dhimpl.NativeNfcSecureElement;
     28 
     29 import android.app.Application;
     30 import android.app.KeyguardManager;
     31 import android.app.PendingIntent;
     32 import android.content.BroadcastReceiver;
     33 import android.content.ContentResolver;
     34 import android.content.Context;
     35 import android.content.Intent;
     36 import android.content.IntentFilter;
     37 import android.content.SharedPreferences;
     38 import android.content.pm.PackageInfo;
     39 import android.content.pm.PackageManager;
     40 import android.media.AudioManager;
     41 import android.media.SoundPool;
     42 import android.net.Uri;
     43 import android.nfc.ErrorCodes;
     44 import android.nfc.FormatException;
     45 import android.nfc.INdefPushCallback;
     46 import android.nfc.INfcAdapter;
     47 import android.nfc.INfcAdapterExtras;
     48 import android.nfc.INfcTag;
     49 import android.nfc.NdefMessage;
     50 import android.nfc.NfcAdapter;
     51 import android.nfc.Tag;
     52 import android.nfc.TechListParcel;
     53 import android.nfc.TransceiveResult;
     54 import android.nfc.tech.Ndef;
     55 import android.nfc.tech.TagTechnology;
     56 import android.os.AsyncTask;
     57 import android.os.Binder;
     58 import android.os.Bundle;
     59 import android.os.Handler;
     60 import android.os.IBinder;
     61 import android.os.Message;
     62 import android.os.PowerManager;
     63 import android.os.Process;
     64 import android.os.RemoteException;
     65 import android.os.ServiceManager;
     66 import android.os.UserHandle;
     67 import android.provider.Settings;
     68 import android.util.Log;
     69 
     70 import java.io.FileDescriptor;
     71 import java.io.IOException;
     72 import java.io.PrintWriter;
     73 import java.util.Arrays;
     74 import java.util.HashMap;
     75 import java.util.HashSet;
     76 import java.util.List;
     77 import java.util.concurrent.ExecutionException;
     78 
     79 public class NfcService implements DeviceHostListener {
     80     private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
     81 
     82     static final boolean DBG = false;
     83     static final String TAG = "NfcService";
     84 
     85     public static final String SERVICE_NAME = "nfc";
     86 
     87     /** Regular NFC permission */
     88     private static final String NFC_PERM = android.Manifest.permission.NFC;
     89     private static final String NFC_PERM_ERROR = "NFC permission required";
     90 
     91     /** NFC ADMIN permission - only for system apps */
     92     private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
     93     private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
     94 
     95     public static final String PREF = "NfcServicePrefs";
     96 
     97     static final String PREF_NFC_ON = "nfc_on";
     98     static final boolean NFC_ON_DEFAULT = true;
     99     static final String PREF_NDEF_PUSH_ON = "ndef_push_on";
    100     static final boolean NDEF_PUSH_ON_DEFAULT = true;
    101     static final String PREF_FIRST_BEAM = "first_beam";
    102     static final String PREF_FIRST_BOOT = "first_boot";
    103     static final String PREF_AIRPLANE_OVERRIDE = "airplane_override";
    104 
    105     static final int MSG_NDEF_TAG = 0;
    106     static final int MSG_CARD_EMULATION = 1;
    107     static final int MSG_LLCP_LINK_ACTIVATION = 2;
    108     static final int MSG_LLCP_LINK_DEACTIVATED = 3;
    109     static final int MSG_TARGET_DESELECTED = 4;
    110     static final int MSG_MOCK_NDEF = 7;
    111     static final int MSG_SE_FIELD_ACTIVATED = 8;
    112     static final int MSG_SE_FIELD_DEACTIVATED = 9;
    113     static final int MSG_SE_APDU_RECEIVED = 10;
    114     static final int MSG_SE_EMV_CARD_REMOVAL = 11;
    115     static final int MSG_SE_MIFARE_ACCESS = 12;
    116     static final int MSG_SE_LISTEN_ACTIVATED = 13;
    117     static final int MSG_SE_LISTEN_DEACTIVATED = 14;
    118 
    119     static final int TASK_ENABLE = 1;
    120     static final int TASK_DISABLE = 2;
    121     static final int TASK_BOOT = 3;
    122     static final int TASK_EE_WIPE = 4;
    123 
    124     // Screen state, used by mScreenState
    125     static final int SCREEN_STATE_UNKNOWN = 0;
    126     static final int SCREEN_STATE_OFF = 1;
    127     static final int SCREEN_STATE_ON_LOCKED = 2;
    128     static final int SCREEN_STATE_ON_UNLOCKED = 3;
    129 
    130     // Copied from com.android.nfc_extras to avoid library dependency
    131     // Must keep in sync with com.android.nfc_extras
    132     static final int ROUTE_OFF = 1;
    133     static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
    134 
    135     /** minimum screen state that enables NFC polling (discovery) */
    136     static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED;
    137 
    138     // Time to wait for NFC controller to initialize before watchdog
    139     // goes off. This time is chosen large, because firmware download
    140     // may be a part of initialization.
    141     static final int INIT_WATCHDOG_MS = 90000;
    142 
    143     // Time to wait for routing to be applied before watchdog
    144     // goes off
    145     static final int ROUTING_WATCHDOG_MS = 10000;
    146 
    147     // for use with playSound()
    148     public static final int SOUND_START = 0;
    149     public static final int SOUND_END = 1;
    150     public static final int SOUND_ERROR = 2;
    151 
    152     public static final String ACTION_RF_FIELD_ON_DETECTED =
    153         "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
    154     public static final String ACTION_RF_FIELD_OFF_DETECTED =
    155         "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
    156     public static final String ACTION_AID_SELECTED =
    157         "com.android.nfc_extras.action.AID_SELECTED";
    158     public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
    159 
    160     public static final String ACTION_APDU_RECEIVED =
    161         "com.android.nfc_extras.action.APDU_RECEIVED";
    162     public static final String EXTRA_APDU_BYTES =
    163         "com.android.nfc_extras.extra.APDU_BYTES";
    164 
    165     public static final String ACTION_EMV_CARD_REMOVAL =
    166         "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
    167 
    168     public static final String ACTION_MIFARE_ACCESS_DETECTED =
    169         "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
    170     public static final String EXTRA_MIFARE_BLOCK =
    171         "com.android.nfc_extras.extra.MIFARE_BLOCK";
    172 
    173     public static final String ACTION_SE_LISTEN_ACTIVATED =
    174             "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED";
    175     public static final String ACTION_SE_LISTEN_DEACTIVATED =
    176             "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED";
    177 
    178     // NFC Execution Environment
    179     // fields below are protected by this
    180     private NativeNfcSecureElement mSecureElement;
    181     private OpenSecureElement mOpenEe;  // null when EE closed
    182     private int mEeRoutingState;  // contactless interface routing
    183 
    184     // fields below must be used only on the UI thread and therefore aren't synchronized
    185     boolean mP2pStarted = false;
    186 
    187     // fields below are used in multiple threads and protected by synchronized(this)
    188     final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
    189     // mSePackages holds packages that accessed the SE, but only for the owner user,
    190     // as SE access is not granted for non-owner users.
    191     HashSet<String> mSePackages = new HashSet<String>();
    192     int mScreenState;
    193     boolean mIsNdefPushEnabled;
    194     boolean mNfceeRouteEnabled;  // current Device Host state of NFC-EE routing
    195     boolean mNfcPollingEnabled;  // current Device Host state of NFC-C polling
    196     List<PackageInfo> mInstalledPackages; // cached version of installed packages
    197 
    198     // mState is protected by this, however it is only modified in onCreate()
    199     // and the default AsyncTask thread so it is read unprotected from that
    200     // thread
    201     int mState;  // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc
    202 
    203     // fields below are final after onCreate()
    204     Context mContext;
    205     private DeviceHost mDeviceHost;
    206     private SharedPreferences mPrefs;
    207     private SharedPreferences.Editor mPrefsEditor;
    208     private PowerManager.WakeLock mRoutingWakeLock;
    209     private PowerManager.WakeLock mEeWakeLock;
    210 
    211     int mStartSound;
    212     int mEndSound;
    213     int mErrorSound;
    214     SoundPool mSoundPool; // playback synchronized on this
    215     P2pLinkManager mP2pLinkManager;
    216     TagService mNfcTagService;
    217     NfcAdapterService mNfcAdapter;
    218     NfcAdapterExtrasService mExtrasService;
    219     boolean mIsAirplaneSensitive;
    220     boolean mIsAirplaneToggleable;
    221     NfceeAccessControl mNfceeAccessControl;
    222 
    223     private NfcDispatcher mNfcDispatcher;
    224     private PowerManager mPowerManager;
    225     private KeyguardManager mKeyguard;
    226 
    227     private static NfcService sService;
    228 
    229     public static void enforceAdminPerm(Context context) {
    230         context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
    231     }
    232 
    233     public void enforceNfceeAdminPerm(String pkg) {
    234         if (pkg == null) {
    235             throw new SecurityException("caller must pass a package name");
    236         }
    237         mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    238         if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) {
    239             throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
    240                     " denies NFCEE access to " + pkg);
    241         }
    242         if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
    243             throw new SecurityException("only the owner is allowed to call SE APIs");
    244         }
    245     }
    246 
    247     public static NfcService getInstance() {
    248         return sService;
    249     }
    250 
    251     @Override
    252     public void onRemoteEndpointDiscovered(TagEndpoint tag) {
    253         sendMessage(NfcService.MSG_NDEF_TAG, tag);
    254     }
    255 
    256     /**
    257      * Notifies transaction
    258      */
    259     @Override
    260     public void onCardEmulationDeselected() {
    261         sendMessage(NfcService.MSG_TARGET_DESELECTED, null);
    262     }
    263 
    264     /**
    265      * Notifies transaction
    266      */
    267     @Override
    268     public void onCardEmulationAidSelected(byte[] aid) {
    269         sendMessage(NfcService.MSG_CARD_EMULATION, aid);
    270     }
    271 
    272     /**
    273      * Notifies P2P Device detected, to activate LLCP link
    274      */
    275     @Override
    276     public void onLlcpLinkActivated(NfcDepEndpoint device) {
    277         sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
    278     }
    279 
    280     /**
    281      * Notifies P2P Device detected, to activate LLCP link
    282      */
    283     @Override
    284     public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
    285         sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
    286     }
    287 
    288     @Override
    289     public void onRemoteFieldActivated() {
    290         sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null);
    291     }
    292 
    293     @Override
    294     public void onRemoteFieldDeactivated() {
    295         sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null);
    296     }
    297 
    298     @Override
    299     public void onSeListenActivated() {
    300         sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null);
    301     }
    302 
    303     @Override
    304     public void onSeListenDeactivated() {
    305         sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null);
    306     }
    307 
    308 
    309     @Override
    310     public void onSeApduReceived(byte[] apdu) {
    311         sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu);
    312     }
    313 
    314     @Override
    315     public void onSeEmvCardRemoval() {
    316         sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null);
    317     }
    318 
    319     @Override
    320     public void onSeMifareAccess(byte[] block) {
    321         sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block);
    322     }
    323 
    324     public NfcService(Application nfcApplication) {
    325         mNfcTagService = new TagService();
    326         mNfcAdapter = new NfcAdapterService();
    327         mExtrasService = new NfcAdapterExtrasService();
    328 
    329         Log.i(TAG, "Starting NFC service");
    330 
    331         sService = this;
    332 
    333         mContext = nfcApplication;
    334         mDeviceHost = new NativeNfcManager(mContext, this);
    335 
    336         HandoverManager handoverManager = new HandoverManager(mContext);
    337         mNfcDispatcher = new NfcDispatcher(mContext, handoverManager);
    338 
    339         mP2pLinkManager = new P2pLinkManager(mContext, handoverManager,
    340                 mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
    341 
    342         mSecureElement = new NativeNfcSecureElement(mContext);
    343         mEeRoutingState = ROUTE_OFF;
    344 
    345         mNfceeAccessControl = new NfceeAccessControl(mContext);
    346 
    347         mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
    348         mPrefsEditor = mPrefs.edit();
    349 
    350         mState = NfcAdapter.STATE_OFF;
    351         mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
    352 
    353         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    354 
    355         mRoutingWakeLock = mPowerManager.newWakeLock(
    356             PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
    357         mEeWakeLock = mPowerManager.newWakeLock(
    358             PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock");
    359 
    360         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
    361         mScreenState = checkScreenState();
    362 
    363         ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
    364 
    365         // Intents only for owner
    366         IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
    367         ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
    368         ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
    369         ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
    370 
    371         mContext.registerReceiver(mOwnerReceiver, ownerFilter);
    372 
    373         ownerFilter = new IntentFilter();
    374         ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
    375         ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    376         ownerFilter.addDataScheme("package");
    377 
    378         mContext.registerReceiver(mOwnerReceiver, ownerFilter);
    379 
    380         // Intents for all users
    381         IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
    382         filter.addAction(Intent.ACTION_SCREEN_OFF);
    383         filter.addAction(Intent.ACTION_SCREEN_ON);
    384         filter.addAction(Intent.ACTION_USER_PRESENT);
    385         registerForAirplaneMode(filter);
    386         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
    387 
    388         updatePackageCache();
    389 
    390         new EnableDisableTask().execute(TASK_BOOT);  // do blocking boot tasks
    391     }
    392 
    393     void initSoundPool() {
    394         synchronized(this) {
    395             if (mSoundPool == null) {
    396                 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
    397                 mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
    398                 mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
    399                 mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
    400             }
    401         }
    402     }
    403 
    404     void releaseSoundPool() {
    405         synchronized(this) {
    406             if (mSoundPool != null) {
    407                 mSoundPool.release();
    408                 mSoundPool = null;
    409             }
    410         }
    411     }
    412 
    413     void registerForAirplaneMode(IntentFilter filter) {
    414         final ContentResolver resolver = mContext.getContentResolver();
    415         final String airplaneModeRadios = Settings.System.getString(resolver,
    416                 Settings.System.AIRPLANE_MODE_RADIOS);
    417         final String toggleableRadios = Settings.System.getString(resolver,
    418                 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
    419 
    420         mIsAirplaneSensitive = airplaneModeRadios == null ? true :
    421                 airplaneModeRadios.contains(Settings.System.RADIO_NFC);
    422         mIsAirplaneToggleable = toggleableRadios == null ? false :
    423             toggleableRadios.contains(Settings.System.RADIO_NFC);
    424 
    425         if (mIsAirplaneSensitive) {
    426             filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    427         }
    428     }
    429 
    430     void updatePackageCache() {
    431         PackageManager pm = mContext.getPackageManager();
    432         List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER);
    433         synchronized (this) {
    434             mInstalledPackages = packages;
    435         }
    436     }
    437 
    438     int checkScreenState() {
    439         if (!mPowerManager.isScreenOn()) {
    440             return SCREEN_STATE_OFF;
    441         } else if (mKeyguard.isKeyguardLocked()) {
    442             return SCREEN_STATE_ON_LOCKED;
    443         } else {
    444             return SCREEN_STATE_ON_UNLOCKED;
    445         }
    446     }
    447 
    448     int doOpenSecureElementConnection() {
    449         mEeWakeLock.acquire();
    450         try {
    451             return mSecureElement.doOpenSecureElementConnection();
    452         } finally {
    453             mEeWakeLock.release();
    454         }
    455     }
    456 
    457     byte[] doTransceive(int handle, byte[] cmd) {
    458         mEeWakeLock.acquire();
    459         try {
    460             return doTransceiveNoLock(handle, cmd);
    461         } finally {
    462             mEeWakeLock.release();
    463         }
    464     }
    465 
    466     byte[] doTransceiveNoLock(int handle, byte[] cmd) {
    467         return mSecureElement.doTransceive(handle, cmd);
    468     }
    469 
    470     void doDisconnect(int handle) {
    471         mEeWakeLock.acquire();
    472         try {
    473             mSecureElement.doDisconnect(handle);
    474         } finally {
    475             mEeWakeLock.release();
    476         }
    477     }
    478 
    479     /**
    480      * Manages tasks that involve turning on/off the NFC controller.
    481      *
    482      * <p>All work that might turn the NFC adapter on or off must be done
    483      * through this task, to keep the handling of mState simple.
    484      * In other words, mState is only modified in these tasks (and we
    485      * don't need a lock to read it in these tasks).
    486      *
    487      * <p>These tasks are all done on the same AsyncTask background
    488      * thread, so they are serialized. Each task may temporarily transition
    489      * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in
    490      * either STATE_ON or STATE_OFF. This way each task can be guaranteed
    491      * of starting in either STATE_OFF or STATE_ON, without needing to hold
    492      * NfcService.this for the entire task.
    493      *
    494      * <p>AsyncTask's are also implicitly queued. This is useful for corner
    495      * cases like turning airplane mode on while TASK_ENABLE is in progress.
    496      * The TASK_DISABLE triggered by airplane mode will be correctly executed
    497      * immediately after TASK_ENABLE is complete. This seems like the most sane
    498      * way to deal with these situations.
    499      *
    500      * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing
    501      * preferences
    502      * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing
    503      * preferences
    504      * <p>{@link #TASK_BOOT} does first boot work and may enable NFC
    505      * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the
    506      * process may temporarily enable the NFC adapter
    507      */
    508     class EnableDisableTask extends AsyncTask<Integer, Void, Void> {
    509         @Override
    510         protected Void doInBackground(Integer... params) {
    511             // Sanity check mState
    512             switch (mState) {
    513                 case NfcAdapter.STATE_TURNING_OFF:
    514                 case NfcAdapter.STATE_TURNING_ON:
    515                     Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " +
    516                             mState);
    517                     return null;
    518             }
    519 
    520             /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND,
    521              * override with the default. THREAD_PRIORITY_BACKGROUND causes
    522              * us to service software I2C too slow for firmware download
    523              * with the NXP PN544.
    524              * TODO: move this to the DAL I2C layer in libnfc-nxp, since this
    525              * problem only occurs on I2C platforms using PN544
    526              */
    527             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    528 
    529             switch (params[0].intValue()) {
    530                 case TASK_ENABLE:
    531                     enableInternal();
    532                     break;
    533                 case TASK_DISABLE:
    534                     disableInternal();
    535                     break;
    536                 case TASK_BOOT:
    537                     Log.d(TAG,"checking on firmware download");
    538                     boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false);
    539                     if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) &&
    540                             (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) {
    541                         Log.d(TAG,"NFC is on. Doing normal stuff");
    542                         enableInternal();
    543                     } else {
    544                         Log.d(TAG,"NFC is off.  Checking firmware version");
    545                         mDeviceHost.checkFirmware();
    546                     }
    547                     if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
    548                         Log.i(TAG, "First Boot");
    549                         mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
    550                         mPrefsEditor.apply();
    551                         executeEeWipe();
    552                     }
    553                     break;
    554                 case TASK_EE_WIPE:
    555                     executeEeWipe();
    556                     break;
    557             }
    558 
    559             // Restore default AsyncTask priority
    560             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    561             return null;
    562         }
    563 
    564         /**
    565          * Enable NFC adapter functions.
    566          * Does not toggle preferences.
    567          */
    568         boolean enableInternal() {
    569             if (mState == NfcAdapter.STATE_ON) {
    570                 return true;
    571             }
    572             Log.i(TAG, "Enabling NFC");
    573             updateState(NfcAdapter.STATE_TURNING_ON);
    574 
    575             WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS);
    576             watchDog.start();
    577             try {
    578                 mRoutingWakeLock.acquire();
    579                 try {
    580                     if (!mDeviceHost.initialize()) {
    581                         Log.w(TAG, "Error enabling NFC");
    582                         updateState(NfcAdapter.STATE_OFF);
    583                         return false;
    584                     }
    585                 } finally {
    586                     mRoutingWakeLock.release();
    587                 }
    588             } finally {
    589                 watchDog.cancel();
    590             }
    591 
    592             synchronized(NfcService.this) {
    593                 mObjectMap.clear();
    594 
    595                 mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
    596                 updateState(NfcAdapter.STATE_ON);
    597             }
    598 
    599             initSoundPool();
    600 
    601             /* Start polling loop */
    602 
    603             applyRouting(true);
    604             return true;
    605         }
    606 
    607         /**
    608          * Disable all NFC adapter functions.
    609          * Does not toggle preferences.
    610          */
    611         boolean disableInternal() {
    612             if (mState == NfcAdapter.STATE_OFF) {
    613                 return true;
    614             }
    615             Log.i(TAG, "Disabling NFC");
    616             updateState(NfcAdapter.STATE_TURNING_OFF);
    617 
    618             /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog.
    619              * Implemented with a new thread (instead of a Handler or AsyncTask),
    620              * because the UI Thread and AsyncTask thread-pools can also get hung
    621              * when the NFC controller stops responding */
    622             WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS);
    623             watchDog.start();
    624 
    625             mP2pLinkManager.enableDisable(false, false);
    626 
    627             synchronized (NfcService.this) {
    628                 if (mOpenEe != null) {
    629                     try {
    630                         _nfcEeClose(-1, mOpenEe.binder);
    631                     } catch (IOException e) { }
    632                 }
    633             }
    634 
    635             // Stop watchdog if tag present
    636             // A convenient way to stop the watchdog properly consists of
    637             // disconnecting the tag. The polling loop shall be stopped before
    638             // to avoid the tag being discovered again.
    639             maybeDisconnectTarget();
    640 
    641             mNfcDispatcher.setForegroundDispatch(null, null, null);
    642 
    643             boolean result = mDeviceHost.deinitialize();
    644             if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result);
    645 
    646             watchDog.cancel();
    647 
    648             updateState(NfcAdapter.STATE_OFF);
    649 
    650             releaseSoundPool();
    651 
    652             return result;
    653         }
    654 
    655         void executeEeWipe() {
    656             // TODO: read SE reset list from /system/etc
    657             byte[][]apdus = mDeviceHost.getWipeApdus();
    658 
    659             if (apdus == null) {
    660                 Log.d(TAG, "No wipe APDUs found");
    661                 return;
    662             }
    663 
    664             boolean tempEnable = mState == NfcAdapter.STATE_OFF;
    665             // Hold a wake-lock over the entire wipe procedure
    666             mEeWakeLock.acquire();
    667             try {
    668                 if (tempEnable && !enableInternal()) {
    669                     Log.w(TAG, "Could not enable NFC to wipe NFC-EE");
    670                     return;
    671                 }
    672                 try {
    673                     // NFC enabled
    674                     int handle = 0;
    675                     try {
    676                         Log.i(TAG, "Executing SE wipe");
    677                         handle = doOpenSecureElementConnection();
    678                         if (handle == 0) {
    679                             Log.w(TAG, "Could not open the secure element");
    680                             return;
    681                         }
    682                         // TODO: remove this hack
    683                         try {
    684                             Thread.sleep(1000);
    685                         } catch (InterruptedException e) {
    686                             // Ignore
    687                         }
    688 
    689                         mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
    690                         try {
    691                             for (byte[] cmd : apdus) {
    692                                 byte[] resp = doTransceiveNoLock(handle, cmd);
    693                                 if (resp == null) {
    694                                     Log.w(TAG, "Transceive failed, could not wipe NFC-EE");
    695                                     break;
    696                                 }
    697                             }
    698                         } finally {
    699                             mDeviceHost.resetTimeouts();
    700                         }
    701                     } finally {
    702                         if (handle != 0) {
    703                             doDisconnect(handle);
    704                         }
    705                     }
    706                 } finally {
    707                     if (tempEnable) {
    708                         disableInternal();
    709                     }
    710                 }
    711             } finally {
    712                 mEeWakeLock.release();
    713             }
    714             Log.i(TAG, "SE wipe done");
    715         }
    716 
    717         void updateState(int newState) {
    718             synchronized (NfcService.this) {
    719                 if (newState == mState) {
    720                     return;
    721                 }
    722                 mState = newState;
    723                 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
    724                 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    725                 intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
    726                 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
    727             }
    728         }
    729     }
    730 
    731     void saveNfcOnSetting(boolean on) {
    732         synchronized (NfcService.this) {
    733             mPrefsEditor.putBoolean(PREF_NFC_ON, on);
    734             mPrefsEditor.apply();
    735         }
    736     }
    737 
    738     public void playSound(int sound) {
    739         synchronized (this) {
    740             if (mSoundPool == null) {
    741                 Log.w(TAG, "Not playing sound when NFC is disabled");
    742                 return;
    743             }
    744             switch (sound) {
    745                 case SOUND_START:
    746                     mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f);
    747                     break;
    748                 case SOUND_END:
    749                     mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f);
    750                     break;
    751                 case SOUND_ERROR:
    752                     mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f);
    753                     break;
    754             }
    755         }
    756     }
    757 
    758 
    759     final class NfcAdapterService extends INfcAdapter.Stub {
    760         @Override
    761         public boolean enable() throws RemoteException {
    762             NfcService.enforceAdminPerm(mContext);
    763 
    764             saveNfcOnSetting(true);
    765 
    766             if (mIsAirplaneSensitive && isAirplaneModeOn()) {
    767                 if (!mIsAirplaneToggleable) {
    768                     Log.i(TAG, "denying enable() request (airplane mode)");
    769                     return false;
    770                 }
    771                 // Make sure the override survives a reboot
    772                 mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true);
    773                 mPrefsEditor.apply();
    774             }
    775             new EnableDisableTask().execute(TASK_ENABLE);
    776 
    777             return true;
    778         }
    779 
    780         @Override
    781         public boolean disable(boolean saveState) throws RemoteException {
    782             NfcService.enforceAdminPerm(mContext);
    783 
    784             if (saveState) {
    785                 saveNfcOnSetting(false);
    786             }
    787 
    788             new EnableDisableTask().execute(TASK_DISABLE);
    789 
    790             return true;
    791         }
    792 
    793         @Override
    794         public boolean isNdefPushEnabled() throws RemoteException {
    795             synchronized (NfcService.this) {
    796                 return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled;
    797             }
    798         }
    799 
    800         @Override
    801         public boolean enableNdefPush() throws RemoteException {
    802             NfcService.enforceAdminPerm(mContext);
    803             synchronized(NfcService.this) {
    804                 if (mIsNdefPushEnabled) {
    805                     return true;
    806                 }
    807                 Log.i(TAG, "enabling NDEF Push");
    808                 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true);
    809                 mPrefsEditor.apply();
    810                 mIsNdefPushEnabled = true;
    811                 if (isNfcEnabled()) {
    812                     mP2pLinkManager.enableDisable(true, true);
    813                 }
    814             }
    815             return true;
    816         }
    817 
    818         @Override
    819         public boolean disableNdefPush() throws RemoteException {
    820             NfcService.enforceAdminPerm(mContext);
    821             synchronized(NfcService.this) {
    822                 if (!mIsNdefPushEnabled) {
    823                     return true;
    824                 }
    825                 Log.i(TAG, "disabling NDEF Push");
    826                 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false);
    827                 mPrefsEditor.apply();
    828                 mIsNdefPushEnabled = false;
    829                 if (isNfcEnabled()) {
    830                     mP2pLinkManager.enableDisable(false, true);
    831                 }
    832             }
    833             return true;
    834         }
    835 
    836         @Override
    837         public void setForegroundDispatch(PendingIntent intent,
    838                 IntentFilter[] filters, TechListParcel techListsParcel) {
    839             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    840 
    841             // Short-cut the disable path
    842             if (intent == null && filters == null && techListsParcel == null) {
    843                 mNfcDispatcher.setForegroundDispatch(null, null, null);
    844                 return;
    845             }
    846 
    847             // Validate the IntentFilters
    848             if (filters != null) {
    849                 if (filters.length == 0) {
    850                     filters = null;
    851                 } else {
    852                     for (IntentFilter filter : filters) {
    853                         if (filter == null) {
    854                             throw new IllegalArgumentException("null IntentFilter");
    855                         }
    856                     }
    857                 }
    858             }
    859 
    860             // Validate the tech lists
    861             String[][] techLists = null;
    862             if (techListsParcel != null) {
    863                 techLists = techListsParcel.getTechLists();
    864             }
    865 
    866             mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
    867         }
    868 
    869         @Override
    870         public void setNdefPushCallback(INdefPushCallback callback) {
    871             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    872             mP2pLinkManager.setNdefCallback(callback);
    873         }
    874 
    875         @Override
    876         public INfcTag getNfcTagInterface() throws RemoteException {
    877             return mNfcTagService;
    878         }
    879 
    880         @Override
    881         public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) {
    882             NfcService.this.enforceNfceeAdminPerm(pkg);
    883             return mExtrasService;
    884         }
    885 
    886         @Override
    887         public int getState() throws RemoteException {
    888             synchronized (NfcService.this) {
    889                 return mState;
    890             }
    891         }
    892 
    893         @Override
    894         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    895             NfcService.this.dump(fd, pw, args);
    896         }
    897 
    898         @Override
    899         public void dispatch(Tag tag) throws RemoteException {
    900             enforceAdminPerm(mContext);
    901             mNfcDispatcher.dispatchTag(tag);
    902         }
    903 
    904         @Override
    905         public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
    906             enforceAdminPerm(mContext);
    907 
    908             mDeviceHost.setP2pInitiatorModes(initiatorModes);
    909             mDeviceHost.setP2pTargetModes(targetModes);
    910             mDeviceHost.disableDiscovery();
    911             mDeviceHost.enableDiscovery();
    912         }
    913     }
    914 
    915     final class TagService extends INfcTag.Stub {
    916         @Override
    917         public int close(int nativeHandle) throws RemoteException {
    918             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    919 
    920             TagEndpoint tag = null;
    921 
    922             if (!isNfcEnabled()) {
    923                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    924             }
    925 
    926             /* find the tag in the hmap */
    927             tag = (TagEndpoint) findObject(nativeHandle);
    928             if (tag != null) {
    929                 /* Remove the device from the hmap */
    930                 unregisterObject(nativeHandle);
    931                 tag.disconnect();
    932                 return ErrorCodes.SUCCESS;
    933             }
    934             /* Restart polling loop for notification */
    935             applyRouting(true);
    936             return ErrorCodes.ERROR_DISCONNECT;
    937         }
    938 
    939         @Override
    940         public int connect(int nativeHandle, int technology) throws RemoteException {
    941             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    942 
    943             TagEndpoint tag = null;
    944 
    945             if (!isNfcEnabled()) {
    946                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    947             }
    948 
    949             /* find the tag in the hmap */
    950             tag = (TagEndpoint) findObject(nativeHandle);
    951             if (tag == null) {
    952                 return ErrorCodes.ERROR_DISCONNECT;
    953             }
    954 
    955             if (!tag.isPresent()) {
    956                 return ErrorCodes.ERROR_DISCONNECT;
    957             }
    958 
    959             // Note that on most tags, all technologies are behind a single
    960             // handle. This means that the connect at the lower levels
    961             // will do nothing, as the tag is already connected to that handle.
    962             if (tag.connect(technology)) {
    963                 return ErrorCodes.SUCCESS;
    964             } else {
    965                 return ErrorCodes.ERROR_DISCONNECT;
    966             }
    967         }
    968 
    969         @Override
    970         public int reconnect(int nativeHandle) throws RemoteException {
    971             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    972 
    973             TagEndpoint tag = null;
    974 
    975             // Check if NFC is enabled
    976             if (!isNfcEnabled()) {
    977                 return ErrorCodes.ERROR_NOT_INITIALIZED;
    978             }
    979 
    980             /* find the tag in the hmap */
    981             tag = (TagEndpoint) findObject(nativeHandle);
    982             if (tag != null) {
    983                 if (tag.reconnect()) {
    984                     return ErrorCodes.SUCCESS;
    985                 } else {
    986                     return ErrorCodes.ERROR_DISCONNECT;
    987                 }
    988             }
    989             return ErrorCodes.ERROR_DISCONNECT;
    990         }
    991 
    992         @Override
    993         public int[] getTechList(int nativeHandle) throws RemoteException {
    994             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
    995 
    996             // Check if NFC is enabled
    997             if (!isNfcEnabled()) {
    998                 return null;
    999             }
   1000 
   1001             /* find the tag in the hmap */
   1002             TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
   1003             if (tag != null) {
   1004                 return tag.getTechList();
   1005             }
   1006             return null;
   1007         }
   1008 
   1009         @Override
   1010         public boolean isPresent(int nativeHandle) throws RemoteException {
   1011             TagEndpoint tag = null;
   1012 
   1013             // Check if NFC is enabled
   1014             if (!isNfcEnabled()) {
   1015                 return false;
   1016             }
   1017 
   1018             /* find the tag in the hmap */
   1019             tag = (TagEndpoint) findObject(nativeHandle);
   1020             if (tag == null) {
   1021                 return false;
   1022             }
   1023 
   1024             return tag.isPresent();
   1025         }
   1026 
   1027         @Override
   1028         public boolean isNdef(int nativeHandle) throws RemoteException {
   1029             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1030 
   1031             TagEndpoint tag = null;
   1032 
   1033             // Check if NFC is enabled
   1034             if (!isNfcEnabled()) {
   1035                 return false;
   1036             }
   1037 
   1038             /* find the tag in the hmap */
   1039             tag = (TagEndpoint) findObject(nativeHandle);
   1040             int[] ndefInfo = new int[2];
   1041             if (tag == null) {
   1042                 return false;
   1043             }
   1044             return tag.checkNdef(ndefInfo);
   1045         }
   1046 
   1047         @Override
   1048         public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
   1049                 throws RemoteException {
   1050             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1051 
   1052             TagEndpoint tag = null;
   1053             byte[] response;
   1054 
   1055             // Check if NFC is enabled
   1056             if (!isNfcEnabled()) {
   1057                 return null;
   1058             }
   1059 
   1060             /* find the tag in the hmap */
   1061             tag = (TagEndpoint) findObject(nativeHandle);
   1062             if (tag != null) {
   1063                 // Check if length is within limits
   1064                 if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
   1065                     return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
   1066                 }
   1067                 int[] targetLost = new int[1];
   1068                 response = tag.transceive(data, raw, targetLost);
   1069                 int result;
   1070                 if (response != null) {
   1071                     result = TransceiveResult.RESULT_SUCCESS;
   1072                 } else if (targetLost[0] == 1) {
   1073                     result = TransceiveResult.RESULT_TAGLOST;
   1074                 } else {
   1075                     result = TransceiveResult.RESULT_FAILURE;
   1076                 }
   1077                 return new TransceiveResult(result, response);
   1078             }
   1079             return null;
   1080         }
   1081 
   1082         @Override
   1083         public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
   1084             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1085 
   1086             TagEndpoint tag;
   1087 
   1088             // Check if NFC is enabled
   1089             if (!isNfcEnabled()) {
   1090                 return null;
   1091             }
   1092 
   1093             /* find the tag in the hmap */
   1094             tag = (TagEndpoint) findObject(nativeHandle);
   1095             if (tag != null) {
   1096                 byte[] buf = tag.readNdef();
   1097                 if (buf == null) {
   1098                     return null;
   1099                 }
   1100 
   1101                 /* Create an NdefMessage */
   1102                 try {
   1103                     return new NdefMessage(buf);
   1104                 } catch (FormatException e) {
   1105                     return null;
   1106                 }
   1107             }
   1108             return null;
   1109         }
   1110 
   1111         @Override
   1112         public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
   1113             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1114 
   1115             TagEndpoint tag;
   1116 
   1117             // Check if NFC is enabled
   1118             if (!isNfcEnabled()) {
   1119                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1120             }
   1121 
   1122             /* find the tag in the hmap */
   1123             tag = (TagEndpoint) findObject(nativeHandle);
   1124             if (tag == null) {
   1125                 return ErrorCodes.ERROR_IO;
   1126             }
   1127 
   1128             if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM;
   1129 
   1130             if (tag.writeNdef(msg.toByteArray())) {
   1131                 return ErrorCodes.SUCCESS;
   1132             } else {
   1133                 return ErrorCodes.ERROR_IO;
   1134             }
   1135 
   1136         }
   1137 
   1138         @Override
   1139         public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
   1140             throw new UnsupportedOperationException();
   1141         }
   1142 
   1143         @Override
   1144         public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
   1145             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1146 
   1147             TagEndpoint tag;
   1148 
   1149             // Check if NFC is enabled
   1150             if (!isNfcEnabled()) {
   1151                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1152             }
   1153 
   1154             /* find the tag in the hmap */
   1155             tag = (TagEndpoint) findObject(nativeHandle);
   1156             if (tag == null) {
   1157                 return ErrorCodes.ERROR_IO;
   1158             }
   1159 
   1160             if (tag.makeReadOnly()) {
   1161                 return ErrorCodes.SUCCESS;
   1162             } else {
   1163                 return ErrorCodes.ERROR_IO;
   1164             }
   1165         }
   1166 
   1167         @Override
   1168         public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
   1169             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1170 
   1171             TagEndpoint tag;
   1172 
   1173             // Check if NFC is enabled
   1174             if (!isNfcEnabled()) {
   1175                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1176             }
   1177 
   1178             /* find the tag in the hmap */
   1179             tag = (TagEndpoint) findObject(nativeHandle);
   1180             if (tag == null) {
   1181                 return ErrorCodes.ERROR_IO;
   1182             }
   1183 
   1184             if (tag.formatNdef(key)) {
   1185                 return ErrorCodes.SUCCESS;
   1186             } else {
   1187                 return ErrorCodes.ERROR_IO;
   1188             }
   1189         }
   1190 
   1191         @Override
   1192         public Tag rediscover(int nativeHandle) throws RemoteException {
   1193             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1194 
   1195             TagEndpoint tag = null;
   1196 
   1197             // Check if NFC is enabled
   1198             if (!isNfcEnabled()) {
   1199                 return null;
   1200             }
   1201 
   1202             /* find the tag in the hmap */
   1203             tag = (TagEndpoint) findObject(nativeHandle);
   1204             if (tag != null) {
   1205                 // For now the prime usecase for rediscover() is to be able
   1206                 // to access the NDEF technology after formatting without
   1207                 // having to remove the tag from the field, or similar
   1208                 // to have access to NdefFormatable in case low-level commands
   1209                 // were used to remove NDEF. So instead of doing a full stack
   1210                 // rediscover (which is poorly supported at the moment anyway),
   1211                 // we simply remove these two technologies and detect them
   1212                 // again.
   1213                 tag.removeTechnology(TagTechnology.NDEF);
   1214                 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
   1215                 tag.findAndReadNdef();
   1216                 // Build a new Tag object to return
   1217                 Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
   1218                         tag.getTechExtras(), tag.getHandle(), this);
   1219                 return newTag;
   1220             }
   1221             return null;
   1222         }
   1223 
   1224         @Override
   1225         public int setTimeout(int tech, int timeout) throws RemoteException {
   1226             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1227             boolean success = mDeviceHost.setTimeout(tech, timeout);
   1228             if (success) {
   1229                 return ErrorCodes.SUCCESS;
   1230             } else {
   1231                 return ErrorCodes.ERROR_INVALID_PARAM;
   1232             }
   1233         }
   1234 
   1235         @Override
   1236         public int getTimeout(int tech) throws RemoteException {
   1237             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1238 
   1239             return mDeviceHost.getTimeout(tech);
   1240         }
   1241 
   1242         @Override
   1243         public void resetTimeouts() throws RemoteException {
   1244             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
   1245 
   1246             mDeviceHost.resetTimeouts();
   1247         }
   1248 
   1249         @Override
   1250         public boolean canMakeReadOnly(int ndefType) throws RemoteException {
   1251             return mDeviceHost.canMakeReadOnly(ndefType);
   1252         }
   1253 
   1254         @Override
   1255         public int getMaxTransceiveLength(int tech) throws RemoteException {
   1256             return mDeviceHost.getMaxTransceiveLength(tech);
   1257         }
   1258 
   1259         @Override
   1260         public boolean getExtendedLengthApdusSupported() throws RemoteException {
   1261             return mDeviceHost.getExtendedLengthApdusSupported();
   1262         }
   1263     }
   1264 
   1265     void _nfcEeClose(int callingPid, IBinder binder) throws IOException {
   1266         // Blocks until a pending open() or transceive() times out.
   1267         //TODO: This is incorrect behavior - the close should interrupt pending
   1268         // operations. However this is not supported by current hardware.
   1269 
   1270         synchronized (NfcService.this) {
   1271             if (!isNfcEnabledOrShuttingDown()) {
   1272                 throw new IOException("NFC adapter is disabled");
   1273             }
   1274             if (mOpenEe == null) {
   1275                 throw new IOException("NFC EE closed");
   1276             }
   1277             if (callingPid != -1 && callingPid != mOpenEe.pid) {
   1278                 throw new SecurityException("Wrong PID");
   1279             }
   1280             if (mOpenEe.binder != binder) {
   1281                 throw new SecurityException("Wrong binder handle");
   1282             }
   1283 
   1284             binder.unlinkToDeath(mOpenEe, 0);
   1285             mDeviceHost.resetTimeouts();
   1286             doDisconnect(mOpenEe.handle);
   1287             mOpenEe = null;
   1288 
   1289             applyRouting(true);
   1290         }
   1291     }
   1292 
   1293     final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub {
   1294         private Bundle writeNoException() {
   1295             Bundle p = new Bundle();
   1296             p.putInt("e", 0);
   1297             return p;
   1298         }
   1299         private Bundle writeIoException(IOException e) {
   1300             Bundle p = new Bundle();
   1301             p.putInt("e", -1);
   1302             p.putString("m", e.getMessage());
   1303             return p;
   1304         }
   1305 
   1306         @Override
   1307         public Bundle open(String pkg, IBinder b) throws RemoteException {
   1308             NfcService.this.enforceNfceeAdminPerm(pkg);
   1309 
   1310             Bundle result;
   1311             try {
   1312                 _open(b);
   1313                 result = writeNoException();
   1314             } catch (IOException e) {
   1315                 result = writeIoException(e);
   1316             }
   1317             return result;
   1318         }
   1319 
   1320         private void _open(IBinder b) throws IOException {
   1321             synchronized(NfcService.this) {
   1322                 if (!isNfcEnabled()) {
   1323                     throw new IOException("NFC adapter is disabled");
   1324                 }
   1325                 if (mOpenEe != null) {
   1326                     throw new IOException("NFC EE already open");
   1327                 }
   1328 
   1329                 int handle = doOpenSecureElementConnection();
   1330                 if (handle == 0) {
   1331                     throw new IOException("NFC EE failed to open");
   1332                 }
   1333                 mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000);
   1334 
   1335                 mOpenEe = new OpenSecureElement(getCallingPid(), handle, b);
   1336                 try {
   1337                     b.linkToDeath(mOpenEe, 0);
   1338                 } catch (RemoteException e) {
   1339                     mOpenEe.binderDied();
   1340                 }
   1341 
   1342                 // Add the calling package to the list of packages that have accessed
   1343                 // the secure element.
   1344                 for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
   1345                     mSePackages.add(packageName);
   1346                 }
   1347            }
   1348         }
   1349 
   1350         @Override
   1351         public Bundle close(String pkg, IBinder binder) throws RemoteException {
   1352             NfcService.this.enforceNfceeAdminPerm(pkg);
   1353 
   1354             Bundle result;
   1355             try {
   1356                 _nfcEeClose(getCallingPid(), binder);
   1357                 result = writeNoException();
   1358             } catch (IOException e) {
   1359                 result = writeIoException(e);
   1360             }
   1361             return result;
   1362         }
   1363 
   1364         @Override
   1365         public Bundle transceive(String pkg, byte[] in) throws RemoteException {
   1366             NfcService.this.enforceNfceeAdminPerm(pkg);
   1367 
   1368             Bundle result;
   1369             byte[] out;
   1370             try {
   1371                 out = _transceive(in);
   1372                 result = writeNoException();
   1373                 result.putByteArray("out", out);
   1374             } catch (IOException e) {
   1375                 result = writeIoException(e);
   1376             }
   1377             return result;
   1378         }
   1379 
   1380         private byte[] _transceive(byte[] data) throws IOException {
   1381             synchronized(NfcService.this) {
   1382                 if (!isNfcEnabled()) {
   1383                     throw new IOException("NFC is not enabled");
   1384                 }
   1385                 if (mOpenEe == null) {
   1386                     throw new IOException("NFC EE is not open");
   1387                 }
   1388                 if (getCallingPid() != mOpenEe.pid) {
   1389                     throw new SecurityException("Wrong PID");
   1390                 }
   1391             }
   1392 
   1393             return doTransceive(mOpenEe.handle, data);
   1394         }
   1395 
   1396         @Override
   1397         public int getCardEmulationRoute(String pkg) throws RemoteException {
   1398             NfcService.this.enforceNfceeAdminPerm(pkg);
   1399             return mEeRoutingState;
   1400         }
   1401 
   1402         @Override
   1403         public void setCardEmulationRoute(String pkg, int route) throws RemoteException {
   1404             NfcService.this.enforceNfceeAdminPerm(pkg);
   1405             mEeRoutingState = route;
   1406             ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask();
   1407             applyRoutingTask.execute();
   1408             try {
   1409                 // Block until route is set
   1410                 applyRoutingTask.get();
   1411             } catch (ExecutionException e) {
   1412                 Log.e(TAG, "failed to set card emulation mode");
   1413             } catch (InterruptedException e) {
   1414                 Log.e(TAG, "failed to set card emulation mode");
   1415             }
   1416         }
   1417 
   1418         @Override
   1419         public void authenticate(String pkg, byte[] token) throws RemoteException {
   1420             NfcService.this.enforceNfceeAdminPerm(pkg);
   1421         }
   1422 
   1423         @Override
   1424         public String getDriverName(String pkg) throws RemoteException {
   1425             NfcService.this.enforceNfceeAdminPerm(pkg);
   1426             return mDeviceHost.getName();
   1427         }
   1428     }
   1429 
   1430     /** resources kept while secure element is open */
   1431     private class OpenSecureElement implements IBinder.DeathRecipient {
   1432         public int pid;  // pid that opened SE
   1433         // binder handle used for DeathReceipient. Must keep
   1434         // a reference to this, otherwise it can get GC'd and
   1435         // the binder stub code might create a different BinderProxy
   1436         // for the same remote IBinder, causing mismatched
   1437         // link()/unlink()
   1438         public IBinder binder;
   1439         public int handle; // low-level handle
   1440         public OpenSecureElement(int pid, int handle, IBinder binder) {
   1441             this.pid = pid;
   1442             this.handle = handle;
   1443             this.binder = binder;
   1444         }
   1445         @Override
   1446         public void binderDied() {
   1447             synchronized (NfcService.this) {
   1448                 Log.i(TAG, "Tracked app " + pid + " died");
   1449                 pid = -1;
   1450                 try {
   1451                     _nfcEeClose(-1, binder);
   1452                 } catch (IOException e) { /* already closed */ }
   1453             }
   1454         }
   1455         @Override
   1456         public String toString() {
   1457             return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=")
   1458                     .append(pid).append(" handle=").append(handle).append("]").toString();
   1459         }
   1460     }
   1461 
   1462     boolean isNfcEnabledOrShuttingDown() {
   1463         synchronized (this) {
   1464             return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF);
   1465         }
   1466     }
   1467 
   1468     boolean isNfcEnabled() {
   1469         synchronized (this) {
   1470             return mState == NfcAdapter.STATE_ON;
   1471         }
   1472     }
   1473 
   1474     class WatchDogThread extends Thread {
   1475         boolean mWatchDogCanceled = false;
   1476         final int mTimeout;
   1477 
   1478         public WatchDogThread(String threadName, int timeout) {
   1479             super(threadName);
   1480             mTimeout = timeout;
   1481         }
   1482 
   1483         @Override
   1484         public void run() {
   1485             boolean slept = false;
   1486             while (!slept) {
   1487                 try {
   1488                     Thread.sleep(mTimeout);
   1489                     slept = true;
   1490                 } catch (InterruptedException e) { }
   1491             }
   1492             synchronized (this) {
   1493                 if (!mWatchDogCanceled) {
   1494                     // Trigger watch-dog
   1495                     Log.e(TAG, "Watchdog fired: name=" + getName() + " threadId=" +
   1496                             getId() + " timeout=" + mTimeout);
   1497                     mDeviceHost.doAbort();
   1498                 }
   1499             }
   1500         }
   1501         public synchronized void cancel() {
   1502             mWatchDogCanceled = true;
   1503         }
   1504     }
   1505 
   1506     /**
   1507      * Read mScreenState and apply NFC-C polling and NFC-EE routing
   1508      */
   1509     void applyRouting(boolean force) {
   1510         synchronized (this) {
   1511             if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) {
   1512                 // PN544 cannot be reconfigured while EE is open
   1513                 return;
   1514             }
   1515             WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS);
   1516 
   1517             try {
   1518                 watchDog.start();
   1519 
   1520                 if (mDeviceHost.enablePN544Quirks() && mScreenState == SCREEN_STATE_OFF) {
   1521                     /* TODO undo this after the LLCP stack is fixed.
   1522                      * Use a different sequence when turning the screen off to
   1523                      * workaround race conditions in pn544 libnfc. The race occurs
   1524                      * when we change routing while there is a P2P target connect.
   1525                      * The async LLCP callback will crash since the routing code
   1526                      * is overwriting globals it relies on.
   1527                      */
   1528                     if (POLLING_MODE > SCREEN_STATE_OFF) {
   1529                         if (force || mNfcPollingEnabled) {
   1530                             Log.d(TAG, "NFC-C OFF, disconnect");
   1531                             mNfcPollingEnabled = false;
   1532                             mDeviceHost.disableDiscovery();
   1533                             maybeDisconnectTarget();
   1534                         }
   1535                     }
   1536                     if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
   1537                         if (force || mNfceeRouteEnabled) {
   1538                             Log.d(TAG, "NFC-EE OFF");
   1539                             mNfceeRouteEnabled = false;
   1540                             mDeviceHost.doDeselectSecureElement();
   1541                         }
   1542                     }
   1543                     return;
   1544                 }
   1545 
   1546                 // configure NFC-EE routing
   1547                 if (mScreenState >= SCREEN_STATE_ON_LOCKED &&
   1548                         mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
   1549                     if (force || !mNfceeRouteEnabled) {
   1550                         Log.d(TAG, "NFC-EE ON");
   1551                         mNfceeRouteEnabled = true;
   1552                         mDeviceHost.doSelectSecureElement();
   1553                     }
   1554                 } else {
   1555                     if (force ||  mNfceeRouteEnabled) {
   1556                         Log.d(TAG, "NFC-EE OFF");
   1557                         mNfceeRouteEnabled = false;
   1558                         mDeviceHost.doDeselectSecureElement();
   1559                     }
   1560                 }
   1561 
   1562                 // configure NFC-C polling
   1563                 if (mScreenState >= POLLING_MODE) {
   1564                     if (force || !mNfcPollingEnabled) {
   1565                         Log.d(TAG, "NFC-C ON");
   1566                         mNfcPollingEnabled = true;
   1567                         mDeviceHost.enableDiscovery();
   1568                     }
   1569                 } else {
   1570                     if (force || mNfcPollingEnabled) {
   1571                         Log.d(TAG, "NFC-C OFF");
   1572                         mNfcPollingEnabled = false;
   1573                         mDeviceHost.disableDiscovery();
   1574                     }
   1575                 }
   1576             } finally {
   1577                 watchDog.cancel();
   1578             }
   1579         }
   1580     }
   1581 
   1582     /** Disconnect any target if present */
   1583     void maybeDisconnectTarget() {
   1584         if (!isNfcEnabledOrShuttingDown()) {
   1585             return;
   1586         }
   1587         Object[] objectsToDisconnect;
   1588         synchronized (this) {
   1589             Object[] objectValues = mObjectMap.values().toArray();
   1590             // Copy the array before we clear mObjectMap,
   1591             // just in case the HashMap values are backed by the same array
   1592             objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length);
   1593             mObjectMap.clear();
   1594         }
   1595         for (Object o : objectsToDisconnect) {
   1596             if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName());
   1597             if (o instanceof TagEndpoint) {
   1598                 // Disconnect from tags
   1599                 TagEndpoint tag = (TagEndpoint) o;
   1600                 tag.disconnect();
   1601             } else if (o instanceof NfcDepEndpoint) {
   1602                 // Disconnect from P2P devices
   1603                 NfcDepEndpoint device = (NfcDepEndpoint) o;
   1604                 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
   1605                     // Remote peer is target, request disconnection
   1606                     device.disconnect();
   1607                 } else {
   1608                     // Remote peer is initiator, we cannot disconnect
   1609                     // Just wait for field removal
   1610                 }
   1611             }
   1612         }
   1613     }
   1614 
   1615     Object findObject(int key) {
   1616         synchronized (this) {
   1617             Object device = mObjectMap.get(key);
   1618             if (device == null) {
   1619                 Log.w(TAG, "Handle not found");
   1620             }
   1621             return device;
   1622         }
   1623     }
   1624 
   1625     void registerTagObject(TagEndpoint tag) {
   1626         synchronized (this) {
   1627             mObjectMap.put(tag.getHandle(), tag);
   1628         }
   1629     }
   1630 
   1631     void unregisterObject(int handle) {
   1632         synchronized (this) {
   1633             mObjectMap.remove(handle);
   1634         }
   1635     }
   1636 
   1637     /** For use by code in this process */
   1638     public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
   1639             throws LlcpException {
   1640         return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength);
   1641     }
   1642 
   1643     /** For use by code in this process */
   1644     public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn)
   1645             throws LlcpException {
   1646         return mDeviceHost.createLlcpConnectionlessSocket(sap, sn);
   1647     }
   1648 
   1649     /** For use by code in this process */
   1650     public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw,
   1651             int linearBufferLength) throws LlcpException {
   1652         return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength);
   1653     }
   1654 
   1655     public void sendMockNdefTag(NdefMessage msg) {
   1656         sendMessage(MSG_MOCK_NDEF, msg);
   1657     }
   1658 
   1659     void sendMessage(int what, Object obj) {
   1660         Message msg = mHandler.obtainMessage();
   1661         msg.what = what;
   1662         msg.obj = obj;
   1663         mHandler.sendMessage(msg);
   1664     }
   1665 
   1666     final class NfcServiceHandler extends Handler {
   1667         @Override
   1668         public void handleMessage(Message msg) {
   1669             switch (msg.what) {
   1670                 case MSG_MOCK_NDEF: {
   1671                     NdefMessage ndefMsg = (NdefMessage) msg.obj;
   1672                     Bundle extras = new Bundle();
   1673                     extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg);
   1674                     extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0);
   1675                     extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY);
   1676                     extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER);
   1677                     Tag tag = Tag.createMockTag(new byte[] { 0x00 },
   1678                             new int[] { TagTechnology.NDEF },
   1679                             new Bundle[] { extras });
   1680                     Log.d(TAG, "mock NDEF tag, starting corresponding activity");
   1681                     Log.d(TAG, tag.toString());
   1682                     boolean delivered = mNfcDispatcher.dispatchTag(tag);
   1683                     if (delivered) {
   1684                         playSound(SOUND_END);
   1685                     } else {
   1686                         playSound(SOUND_ERROR);
   1687                     }
   1688                     break;
   1689                 }
   1690 
   1691                 case MSG_NDEF_TAG:
   1692                     if (DBG) Log.d(TAG, "Tag detected, notifying applications");
   1693                     TagEndpoint tag = (TagEndpoint) msg.obj;
   1694                     playSound(SOUND_START);
   1695                     NdefMessage ndefMsg = tag.findAndReadNdef();
   1696 
   1697                     if (ndefMsg != null) {
   1698                         tag.startPresenceChecking();
   1699                         dispatchTagEndpoint(tag);
   1700                     } else {
   1701                         if (tag.reconnect()) {
   1702                             tag.startPresenceChecking();
   1703                             dispatchTagEndpoint(tag);
   1704                         } else {
   1705                             tag.disconnect();
   1706                             playSound(SOUND_ERROR);
   1707                         }
   1708                     }
   1709                     break;
   1710 
   1711                 case MSG_CARD_EMULATION:
   1712                     if (DBG) Log.d(TAG, "Card Emulation message");
   1713                     byte[] aid = (byte[]) msg.obj;
   1714                     /* Send broadcast */
   1715                     Intent aidIntent = new Intent();
   1716                     aidIntent.setAction(ACTION_AID_SELECTED);
   1717                     aidIntent.putExtra(EXTRA_AID, aid);
   1718                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED);
   1719                     sendSeBroadcast(aidIntent);
   1720                     break;
   1721 
   1722                 case MSG_SE_EMV_CARD_REMOVAL:
   1723                     if (DBG) Log.d(TAG, "Card Removal message");
   1724                     /* Send broadcast */
   1725                     Intent cardRemovalIntent = new Intent();
   1726                     cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL);
   1727                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL);
   1728                     sendSeBroadcast(cardRemovalIntent);
   1729                     break;
   1730 
   1731                 case MSG_SE_APDU_RECEIVED:
   1732                     if (DBG) Log.d(TAG, "APDU Received message");
   1733                     byte[] apduBytes = (byte[]) msg.obj;
   1734                     /* Send broadcast */
   1735                     Intent apduReceivedIntent = new Intent();
   1736                     apduReceivedIntent.setAction(ACTION_APDU_RECEIVED);
   1737                     if (apduBytes != null && apduBytes.length > 0) {
   1738                         apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes);
   1739                     }
   1740                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED);
   1741                     sendSeBroadcast(apduReceivedIntent);
   1742                     break;
   1743 
   1744                 case MSG_SE_MIFARE_ACCESS:
   1745                     if (DBG) Log.d(TAG, "MIFARE access message");
   1746                     /* Send broadcast */
   1747                     byte[] mifareCmd = (byte[]) msg.obj;
   1748                     Intent mifareAccessIntent = new Intent();
   1749                     mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED);
   1750                     if (mifareCmd != null && mifareCmd.length > 1) {
   1751                         int mifareBlock = mifareCmd[1] & 0xff;
   1752                         if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock);
   1753                         mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock);
   1754                     }
   1755                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED);
   1756                     sendSeBroadcast(mifareAccessIntent);
   1757                     break;
   1758 
   1759                 case MSG_LLCP_LINK_ACTIVATION:
   1760                     llcpActivated((NfcDepEndpoint) msg.obj);
   1761                     break;
   1762 
   1763                 case MSG_LLCP_LINK_DEACTIVATED:
   1764                     NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
   1765                     boolean needsDisconnect = false;
   1766 
   1767                     Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
   1768                     synchronized (NfcService.this) {
   1769                         /* Check if the device has been already unregistered */
   1770                         if (mObjectMap.remove(device.getHandle()) != null) {
   1771                             /* Disconnect if we are initiator */
   1772                             if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
   1773                                 if (DBG) Log.d(TAG, "disconnecting from target");
   1774                                 needsDisconnect = true;
   1775                             } else {
   1776                                 if (DBG) Log.d(TAG, "not disconnecting from initiator");
   1777                             }
   1778                         }
   1779                     }
   1780                     if (needsDisconnect) {
   1781                         device.disconnect();  // restarts polling loop
   1782                     }
   1783 
   1784                     mP2pLinkManager.onLlcpDeactivated();
   1785                     break;
   1786 
   1787                 case MSG_TARGET_DESELECTED:
   1788                     /* Broadcast Intent Target Deselected */
   1789                     if (DBG) Log.d(TAG, "Target Deselected");
   1790                     Intent intent = new Intent();
   1791                     intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
   1792                     if (DBG) Log.d(TAG, "Broadcasting Intent");
   1793                     mContext.sendOrderedBroadcast(intent, NFC_PERM);
   1794                     break;
   1795 
   1796                 case MSG_SE_FIELD_ACTIVATED: {
   1797                     if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
   1798                     Intent eventFieldOnIntent = new Intent();
   1799                     eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
   1800                     sendSeBroadcast(eventFieldOnIntent);
   1801                     break;
   1802                 }
   1803 
   1804                 case MSG_SE_FIELD_DEACTIVATED: {
   1805                     if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
   1806                     Intent eventFieldOffIntent = new Intent();
   1807                     eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
   1808                     sendSeBroadcast(eventFieldOffIntent);
   1809                     break;
   1810                 }
   1811 
   1812                 case MSG_SE_LISTEN_ACTIVATED: {
   1813                     if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED");
   1814                     Intent listenModeActivated = new Intent();
   1815                     listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED);
   1816                     sendSeBroadcast(listenModeActivated);
   1817                     break;
   1818                 }
   1819 
   1820                 case MSG_SE_LISTEN_DEACTIVATED: {
   1821                     if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED");
   1822                     Intent listenModeDeactivated = new Intent();
   1823                     listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED);
   1824                     sendSeBroadcast(listenModeDeactivated);
   1825                     break;
   1826                 }
   1827 
   1828                 default:
   1829                     Log.e(TAG, "Unknown message received");
   1830                     break;
   1831             }
   1832         }
   1833 
   1834         private void sendSeBroadcast(Intent intent) {
   1835             intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
   1836             // Resume app switches so the receivers can start activites without delay
   1837             mNfcDispatcher.resumeAppSwitches();
   1838 
   1839             synchronized(this) {
   1840                 for (PackageInfo pkg : mInstalledPackages) {
   1841                     if (pkg != null && pkg.applicationInfo != null) {
   1842                         if (mNfceeAccessControl.check(pkg.applicationInfo)) {
   1843                             intent.setPackage(pkg.packageName);
   1844                             mContext.sendBroadcast(intent);
   1845                         }
   1846                     }
   1847                 }
   1848             }
   1849         }
   1850 
   1851         private boolean llcpActivated(NfcDepEndpoint device) {
   1852             Log.d(TAG, "LLCP Activation message");
   1853 
   1854             if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
   1855                 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
   1856                 if (device.connect()) {
   1857                     /* Check LLCP compliancy */
   1858                     if (mDeviceHost.doCheckLlcp()) {
   1859                         /* Activate LLCP Link */
   1860                         if (mDeviceHost.doActivateLlcp()) {
   1861                             if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
   1862                             synchronized (NfcService.this) {
   1863                                 // Register P2P device
   1864                                 mObjectMap.put(device.getHandle(), device);
   1865                             }
   1866                             mP2pLinkManager.onLlcpActivated();
   1867                             return true;
   1868                         } else {
   1869                             /* should not happen */
   1870                             Log.w(TAG, "Initiator LLCP activation failed. Disconnect.");
   1871                             device.disconnect();
   1872                         }
   1873                     } else {
   1874                         if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
   1875                         device.disconnect();
   1876                     }
   1877                 } else {
   1878                     if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted.");
   1879                     /*
   1880                      * The polling loop should have been restarted in failing
   1881                      * doConnect
   1882                      */
   1883                 }
   1884             } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
   1885                 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
   1886                 /* Check LLCP compliancy */
   1887                 if (mDeviceHost.doCheckLlcp()) {
   1888                     /* Activate LLCP Link */
   1889                     if (mDeviceHost.doActivateLlcp()) {
   1890                         if (DBG) Log.d(TAG, "Target Activate LLCP OK");
   1891                         synchronized (NfcService.this) {
   1892                             // Register P2P device
   1893                             mObjectMap.put(device.getHandle(), device);
   1894                         }
   1895                         mP2pLinkManager.onLlcpActivated();
   1896                         return true;
   1897                     }
   1898                 } else {
   1899                     Log.w(TAG, "checkLlcp failed");
   1900                 }
   1901             }
   1902 
   1903             return false;
   1904         }
   1905 
   1906         private void dispatchTagEndpoint(TagEndpoint tagEndpoint) {
   1907             Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
   1908                     tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
   1909             registerTagObject(tagEndpoint);
   1910             if (!mNfcDispatcher.dispatchTag(tag)) {
   1911                 unregisterObject(tagEndpoint.getHandle());
   1912                 playSound(SOUND_ERROR);
   1913             } else {
   1914                 playSound(SOUND_END);
   1915             }
   1916         }
   1917     }
   1918 
   1919     private NfcServiceHandler mHandler = new NfcServiceHandler();
   1920 
   1921     class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> {
   1922         @Override
   1923         protected Void doInBackground(Integer... params) {
   1924             synchronized (NfcService.this) {
   1925                 if (params == null || params.length != 1) {
   1926                     // force apply current routing
   1927                     applyRouting(true);
   1928                     return null;
   1929                 }
   1930                 mScreenState = params[0].intValue();
   1931 
   1932                 mRoutingWakeLock.acquire();
   1933                 try {
   1934                     applyRouting(false);
   1935                 } finally {
   1936                     mRoutingWakeLock.release();
   1937                 }
   1938                 return null;
   1939             }
   1940         }
   1941     }
   1942 
   1943     private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
   1944         @Override
   1945         public void onReceive(Context context, Intent intent) {
   1946             String action = intent.getAction();
   1947             if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
   1948                     action.equals(Intent.ACTION_PACKAGE_ADDED) ||
   1949                     action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
   1950                     action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
   1951                 updatePackageCache();
   1952 
   1953                 if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
   1954                     // Clear the NFCEE access cache in case a UID gets recycled
   1955                     mNfceeAccessControl.invalidateCache();
   1956 
   1957                     boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
   1958                     if (dataRemoved) {
   1959                         Uri data = intent.getData();
   1960                         if (data == null) return;
   1961                         String packageName = data.getSchemeSpecificPart();
   1962 
   1963                         synchronized (NfcService.this) {
   1964                             if (mSePackages.contains(packageName)) {
   1965                                 new EnableDisableTask().execute(TASK_EE_WIPE);
   1966                                 mSePackages.remove(packageName);
   1967                             }
   1968                         }
   1969                     }
   1970                 }
   1971             } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
   1972                 EnableDisableTask eeWipeTask = new EnableDisableTask();
   1973                 eeWipeTask.execute(TASK_EE_WIPE);
   1974                 try {
   1975                     eeWipeTask.get();  // blocks until EE wipe is complete
   1976                 } catch (ExecutionException e) {
   1977                     Log.w(TAG, "failed to wipe NFC-EE");
   1978                 } catch (InterruptedException e) {
   1979                     Log.w(TAG, "failed to wipe NFC-EE");
   1980                 }
   1981             }
   1982         }
   1983     };
   1984 
   1985     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
   1986         @Override
   1987         public void onReceive(Context context, Intent intent) {
   1988             String action = intent.getAction();
   1989             if (action.equals(
   1990                     NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
   1991                 // Perform applyRouting() in AsyncTask to serialize blocking calls
   1992                 new ApplyRoutingTask().execute();
   1993             } else if (action.equals(Intent.ACTION_SCREEN_ON)
   1994                     || action.equals(Intent.ACTION_SCREEN_OFF)
   1995                     || action.equals(Intent.ACTION_USER_PRESENT)) {
   1996                 // Perform applyRouting() in AsyncTask to serialize blocking calls
   1997                 int screenState = SCREEN_STATE_OFF;
   1998                 if (action.equals(Intent.ACTION_SCREEN_OFF)) {
   1999                     screenState = SCREEN_STATE_OFF;
   2000                 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
   2001                     screenState = mKeyguard.isKeyguardLocked() ?
   2002                             SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
   2003                 } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
   2004                     screenState = SCREEN_STATE_ON_UNLOCKED;
   2005                 }
   2006                 new ApplyRoutingTask().execute(Integer.valueOf(screenState));
   2007             } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
   2008                 boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
   2009                 // Query the airplane mode from Settings.System just to make sure that
   2010                 // some random app is not sending this intent
   2011                 if (isAirplaneModeOn != isAirplaneModeOn()) {
   2012                     return;
   2013                 }
   2014                 if (!mIsAirplaneSensitive) {
   2015                     return;
   2016                 }
   2017                 mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false);
   2018                 mPrefsEditor.apply();
   2019                 if (isAirplaneModeOn) {
   2020                     new EnableDisableTask().execute(TASK_DISABLE);
   2021                 } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
   2022                     new EnableDisableTask().execute(TASK_ENABLE);
   2023                 }
   2024             }
   2025         }
   2026     };
   2027 
   2028     /** Returns true if airplane mode is currently on */
   2029     boolean isAirplaneModeOn() {
   2030         return Settings.System.getInt(mContext.getContentResolver(),
   2031                 Settings.System.AIRPLANE_MODE_ON, 0) == 1;
   2032     }
   2033 
   2034     /** for debugging only - no i18n */
   2035     static String stateToString(int state) {
   2036         switch (state) {
   2037             case NfcAdapter.STATE_OFF:
   2038                 return "off";
   2039             case NfcAdapter.STATE_TURNING_ON:
   2040                 return "turning on";
   2041             case NfcAdapter.STATE_ON:
   2042                 return "on";
   2043             case NfcAdapter.STATE_TURNING_OFF:
   2044                 return "turning off";
   2045             default:
   2046                 return "<error>";
   2047         }
   2048     }
   2049 
   2050     /** For debugging only - no i18n */
   2051     static String screenStateToString(int screenState) {
   2052         switch (screenState) {
   2053             case SCREEN_STATE_OFF:
   2054                 return "OFF";
   2055             case SCREEN_STATE_ON_LOCKED:
   2056                 return "ON_LOCKED";
   2057             case SCREEN_STATE_ON_UNLOCKED:
   2058                 return "ON_UNLOCKED";
   2059             default:
   2060                 return "UNKNOWN";
   2061         }
   2062     }
   2063 
   2064     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   2065         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
   2066                 != PackageManager.PERMISSION_GRANTED) {
   2067             pw.println("Permission Denial: can't dump nfc from from pid="
   2068                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
   2069                     + " without permission " + android.Manifest.permission.DUMP);
   2070             return;
   2071         }
   2072 
   2073         synchronized (this) {
   2074             pw.println("mState=" + stateToString(mState));
   2075             pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled);
   2076             pw.println("mScreenState=" + screenStateToString(mScreenState));
   2077             pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled);
   2078             pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled);
   2079             pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive);
   2080             pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable);
   2081             pw.println("mOpenEe=" + mOpenEe);
   2082             mP2pLinkManager.dump(fd, pw, args);
   2083             mNfceeAccessControl.dump(fd, pw, args);
   2084             mNfcDispatcher.dump(fd, pw, args);
   2085             pw.println(mDeviceHost.dump());
   2086 
   2087         }
   2088     }
   2089 }
   2090