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