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 android.app.ActivityManager;
     20 import android.app.Application;
     21 import android.app.KeyguardManager;
     22 import android.app.PendingIntent;
     23 import android.app.admin.DevicePolicyManager;
     24 import android.content.BroadcastReceiver;
     25 import android.content.ComponentName;
     26 import android.content.ContentResolver;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.IntentFilter;
     30 import android.content.SharedPreferences;
     31 import android.content.pm.IPackageManager;
     32 import android.content.pm.PackageInfo;
     33 import android.content.pm.PackageManager;
     34 import android.content.pm.UserInfo;
     35 import android.content.res.Resources.NotFoundException;
     36 import android.media.AudioManager;
     37 import android.media.SoundPool;
     38 import android.nfc.BeamShareData;
     39 import android.nfc.ErrorCodes;
     40 import android.nfc.FormatException;
     41 import android.nfc.IAppCallback;
     42 import android.nfc.INfcAdapter;
     43 import android.nfc.INfcAdapterExtras;
     44 import android.nfc.INfcCardEmulation;
     45 import android.nfc.INfcFCardEmulation;
     46 import android.nfc.INfcTag;
     47 import android.nfc.INfcUnlockHandler;
     48 import android.nfc.ITagRemovedCallback;
     49 import android.nfc.NdefMessage;
     50 import android.nfc.NfcAdapter;
     51 import android.nfc.Tag;
     52 import android.nfc.TechListParcel;
     53 import android.nfc.TransceiveResult;
     54 import android.nfc.tech.Ndef;
     55 import android.nfc.tech.TagTechnology;
     56 import android.os.AsyncTask;
     57 import android.os.Binder;
     58 import android.os.Build;
     59 import android.os.Bundle;
     60 import android.os.Handler;
     61 import android.os.IBinder;
     62 import android.os.Message;
     63 import android.os.PowerManager;
     64 import android.os.Process;
     65 import android.os.RemoteException;
     66 import android.os.ServiceManager;
     67 import android.os.SystemClock;
     68 import android.os.UserHandle;
     69 import android.os.UserManager;
     70 import android.provider.Settings;
     71 import android.util.Log;
     72 
     73 import com.android.nfc.DeviceHost.DeviceHostListener;
     74 import com.android.nfc.DeviceHost.LlcpConnectionlessSocket;
     75 import com.android.nfc.DeviceHost.LlcpServerSocket;
     76 import com.android.nfc.DeviceHost.LlcpSocket;
     77 import com.android.nfc.DeviceHost.NfcDepEndpoint;
     78 import com.android.nfc.DeviceHost.TagEndpoint;
     79 import com.android.nfc.cardemulation.CardEmulationManager;
     80 import com.android.nfc.dhimpl.NativeNfcManager;
     81 import com.android.nfc.handover.HandoverDataParser;
     82 
     83 import java.io.FileDescriptor;
     84 import java.io.PrintWriter;
     85 import java.nio.ByteBuffer;
     86 import java.util.Arrays;
     87 import java.util.ArrayList;
     88 import java.util.HashMap;
     89 import java.util.List;
     90 import java.util.Map;
     91 import java.util.NoSuchElementException;
     92 
     93 
     94 public class NfcService implements DeviceHostListener {
     95     static final boolean DBG = false;
     96     static final String TAG = "NfcService";
     97 
     98     public static final String SERVICE_NAME = "nfc";
     99 
    100     public static final String PREF = "NfcServicePrefs";
    101 
    102     static final String PREF_NFC_ON = "nfc_on";
    103     static final boolean NFC_ON_DEFAULT = true;
    104     static final String PREF_NDEF_PUSH_ON = "ndef_push_on";
    105     static final boolean NDEF_PUSH_ON_DEFAULT = true;
    106     static final String PREF_FIRST_BEAM = "first_beam";
    107     static final String PREF_FIRST_BOOT = "first_boot";
    108 
    109     static final int MSG_NDEF_TAG = 0;
    110     static final int MSG_LLCP_LINK_ACTIVATION = 1;
    111     static final int MSG_LLCP_LINK_DEACTIVATED = 2;
    112     static final int MSG_MOCK_NDEF = 3;
    113     static final int MSG_LLCP_LINK_FIRST_PACKET = 4;
    114     static final int MSG_ROUTE_AID = 5;
    115     static final int MSG_UNROUTE_AID = 6;
    116     static final int MSG_COMMIT_ROUTING = 7;
    117     static final int MSG_INVOKE_BEAM = 8;
    118     static final int MSG_RF_FIELD_ACTIVATED = 9;
    119     static final int MSG_RF_FIELD_DEACTIVATED = 10;
    120     static final int MSG_RESUME_POLLING = 11;
    121     static final int MSG_REGISTER_T3T_IDENTIFIER = 12;
    122     static final int MSG_DEREGISTER_T3T_IDENTIFIER = 13;
    123     static final int MSG_TAG_DEBOUNCE = 14;
    124 
    125     static final long MAX_POLLING_PAUSE_TIMEOUT = 40000;
    126 
    127     static final int TASK_ENABLE = 1;
    128     static final int TASK_DISABLE = 2;
    129     static final int TASK_BOOT = 3;
    130 
    131     // Polling technology masks
    132     static final int NFC_POLL_A = 0x01;
    133     static final int NFC_POLL_B = 0x02;
    134     static final int NFC_POLL_F = 0x04;
    135     static final int NFC_POLL_ISO15693 = 0x08;
    136     static final int NFC_POLL_B_PRIME = 0x10;
    137     static final int NFC_POLL_KOVIO = 0x20;
    138 
    139     // minimum screen state that enables NFC polling
    140     static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
    141 
    142     // Time to wait for NFC controller to initialize before watchdog
    143     // goes off. This time is chosen large, because firmware download
    144     // may be a part of initialization.
    145     static final int INIT_WATCHDOG_MS = 90000;
    146 
    147     // Time to wait for routing to be applied before watchdog
    148     // goes off
    149     static final int ROUTING_WATCHDOG_MS = 10000;
    150 
    151     // Default delay used for presence checks
    152     static final int DEFAULT_PRESENCE_CHECK_DELAY = 125;
    153 
    154     // The amount of time we wait before manually launching
    155     // the Beam animation when called through the share menu.
    156     static final int INVOKE_BEAM_DELAY_MS = 1000;
    157 
    158     // RF field events as defined in NFC extras
    159     public static final String ACTION_RF_FIELD_ON_DETECTED =
    160             "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
    161     public static final String ACTION_RF_FIELD_OFF_DETECTED =
    162             "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
    163 
    164     // for use with playSound()
    165     public static final int SOUND_START = 0;
    166     public static final int SOUND_END = 1;
    167     public static final int SOUND_ERROR = 2;
    168 
    169     public static final String ACTION_LLCP_UP =
    170             "com.android.nfc.action.LLCP_UP";
    171 
    172     public static final String ACTION_LLCP_DOWN =
    173             "com.android.nfc.action.LLCP_DOWN";
    174 
    175     // Timeout to re-apply routing if a tag was present and we postponed it
    176     private static final int APPLY_ROUTING_RETRY_TIMEOUT_MS = 5000;
    177 
    178     private final UserManager mUserManager;
    179 
    180     // NFC Execution Environment
    181     // fields below are protected by this
    182     private final ReaderModeDeathRecipient mReaderModeDeathRecipient =
    183             new ReaderModeDeathRecipient();
    184     private final NfcUnlockManager mNfcUnlockManager;
    185 
    186     private final NfceeAccessControl mNfceeAccessControl;
    187 
    188     List<PackageInfo> mInstalledPackages; // cached version of installed packages
    189 
    190     // fields below are used in multiple threads and protected by synchronized(this)
    191     final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
    192     int mScreenState;
    193     boolean mInProvisionMode; // whether we're in setup wizard and enabled NFC provisioning
    194     boolean mIsNdefPushEnabled;
    195     NfcDiscoveryParameters mCurrentDiscoveryParameters =
    196             NfcDiscoveryParameters.getNfcOffParameters();
    197 
    198     ReaderModeParams mReaderModeParams;
    199 
    200     private int mUserId;
    201     boolean mPollingPaused;
    202 
    203     byte mDebounceTagUid[];
    204     int mDebounceTagDebounceMs;
    205     ITagRemovedCallback mDebounceTagRemovedCallback;
    206 
    207     // mState is protected by this, however it is only modified in onCreate()
    208     // and the default AsyncTask thread so it is read unprotected from that
    209     // thread
    210     int mState;  // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc
    211     // fields below are final after onCreate()
    212     Context mContext;
    213     private DeviceHost mDeviceHost;
    214     private SharedPreferences mPrefs;
    215     private SharedPreferences.Editor mPrefsEditor;
    216     private PowerManager.WakeLock mRoutingWakeLock;
    217 
    218     int mStartSound;
    219     int mEndSound;
    220     int mErrorSound;
    221     SoundPool mSoundPool; // playback synchronized on this
    222     P2pLinkManager mP2pLinkManager;
    223     TagService mNfcTagService;
    224     NfcAdapterService mNfcAdapter;
    225     boolean mIsDebugBuild;
    226     boolean mIsHceCapable;
    227     boolean mIsHceFCapable;
    228 
    229     private NfcDispatcher mNfcDispatcher;
    230     private PowerManager mPowerManager;
    231     private KeyguardManager mKeyguard;
    232     private HandoverDataParser mHandoverDataParser;
    233     private ContentResolver mContentResolver;
    234     private CardEmulationManager mCardEmulationManager;
    235 
    236     private ScreenStateHelper mScreenStateHelper;
    237     private ForegroundUtils mForegroundUtils;
    238 
    239     private static NfcService sService;
    240 
    241     public static NfcService getInstance() {
    242         return sService;
    243     }
    244 
    245     @Override
    246     public void onRemoteEndpointDiscovered(TagEndpoint tag) {
    247         sendMessage(NfcService.MSG_NDEF_TAG, tag);
    248     }
    249 
    250     /**
    251      * Notifies transaction
    252      */
    253     @Override
    254     public void onHostCardEmulationActivated(int technology) {
    255         if (mCardEmulationManager != null) {
    256             mCardEmulationManager.onHostCardEmulationActivated(technology);
    257         }
    258     }
    259 
    260     @Override
    261     public void onHostCardEmulationData(int technology, byte[] data) {
    262         if (mCardEmulationManager != null) {
    263             mCardEmulationManager.onHostCardEmulationData(technology, data);
    264         }
    265     }
    266 
    267     @Override
    268     public void onHostCardEmulationDeactivated(int technology) {
    269         if (mCardEmulationManager != null) {
    270             mCardEmulationManager.onHostCardEmulationDeactivated(technology);
    271         }
    272     }
    273 
    274     /**
    275      * Notifies P2P Device detected, to activate LLCP link
    276      */
    277     @Override
    278     public void onLlcpLinkActivated(NfcDepEndpoint device) {
    279         sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
    280     }
    281 
    282     /**
    283      * Notifies P2P Device detected, to activate LLCP link
    284      */
    285     @Override
    286     public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
    287         sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
    288     }
    289 
    290     /**
    291      * Notifies P2P Device detected, first packet received over LLCP link
    292      */
    293     @Override
    294     public void onLlcpFirstPacketReceived(NfcDepEndpoint device) {
    295         sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device);
    296     }
    297 
    298     @Override
    299     public void onRemoteFieldActivated() {
    300         sendMessage(NfcService.MSG_RF_FIELD_ACTIVATED, null);
    301     }
    302 
    303     @Override
    304     public void onRemoteFieldDeactivated() {
    305         sendMessage(NfcService.MSG_RF_FIELD_DEACTIVATED, null);
    306     }
    307 
    308     final class ReaderModeParams {
    309         public int flags;
    310         public IAppCallback callback;
    311         public int presenceCheckDelay;
    312     }
    313 
    314     public NfcService(Application nfcApplication) {
    315         mUserId = ActivityManager.getCurrentUser();
    316         mContext = nfcApplication;
    317 
    318         mNfcTagService = new TagService();
    319         mNfcAdapter = new NfcAdapterService();
    320         Log.i(TAG, "Starting NFC service");
    321 
    322         sService = this;
    323 
    324         mScreenStateHelper = new ScreenStateHelper(mContext);
    325         mContentResolver = mContext.getContentResolver();
    326         mDeviceHost = new NativeNfcManager(mContext, this);
    327 
    328         mNfcUnlockManager = NfcUnlockManager.getInstance();
    329 
    330         mHandoverDataParser = new HandoverDataParser();
    331         boolean isNfcProvisioningEnabled = false;
    332         try {
    333             isNfcProvisioningEnabled = mContext.getResources().getBoolean(
    334                     R.bool.enable_nfc_provisioning);
    335         } catch (NotFoundException e) {
    336         }
    337 
    338         if (isNfcProvisioningEnabled) {
    339             mInProvisionMode = Settings.Secure.getInt(mContentResolver,
    340                     Settings.Global.DEVICE_PROVISIONED, 0) == 0;
    341         } else {
    342             mInProvisionMode = false;
    343         }
    344 
    345         mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
    346         mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
    347                 mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
    348 
    349         mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
    350         mPrefsEditor = mPrefs.edit();
    351 
    352         mNfceeAccessControl = new NfceeAccessControl(mContext);
    353 
    354         mState = NfcAdapter.STATE_OFF;
    355         mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
    356         setBeamShareActivityState(mIsNdefPushEnabled);
    357 
    358         mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
    359 
    360         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    361 
    362         mRoutingWakeLock = mPowerManager.newWakeLock(
    363                 PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
    364 
    365         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
    366         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    367 
    368         mScreenState = mScreenStateHelper.checkScreenState();
    369 
    370         // Intents for all users
    371         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
    372         filter.addAction(Intent.ACTION_SCREEN_ON);
    373         filter.addAction(Intent.ACTION_USER_PRESENT);
    374         filter.addAction(Intent.ACTION_USER_SWITCHED);
    375         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
    376 
    377         IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
    378         ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
    379         mContext.registerReceiver(mOwnerReceiver, ownerFilter);
    380 
    381         ownerFilter = new IntentFilter();
    382         ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
    383         ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
    384         ownerFilter.addDataScheme("package");
    385         mContext.registerReceiver(mOwnerReceiver, ownerFilter);
    386 
    387         IntentFilter policyFilter = new IntentFilter(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    388         mContext.registerReceiverAsUser(mPolicyReceiver, UserHandle.ALL, policyFilter, null, null);
    389 
    390         updatePackageCache();
    391 
    392         PackageManager pm = mContext.getPackageManager();
    393         mIsHceCapable =
    394                 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) ||
    395                 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
    396         mIsHceFCapable =
    397                 pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
    398         if (mIsHceCapable) {
    399             mCardEmulationManager = new CardEmulationManager(mContext);
    400         }
    401         mForegroundUtils = ForegroundUtils.getInstance();
    402 
    403         // Make sure this is only called when object construction is complete.
    404         ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
    405 
    406         new EnableDisableTask().execute(TASK_BOOT);  // do blocking boot tasks
    407     }
    408 
    409     void initSoundPool() {
    410         synchronized (this) {
    411             if (mSoundPool == null) {
    412                 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
    413                 mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
    414                 mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
    415                 mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
    416             }
    417         }
    418     }
    419 
    420     void releaseSoundPool() {
    421         synchronized (this) {
    422             if (mSoundPool != null) {
    423                 mSoundPool.release();
    424                 mSoundPool = null;
    425             }
    426         }
    427     }
    428 
    429     void updatePackageCache() {
    430         PackageManager pm = mContext.getPackageManager();
    431         List<PackageInfo> packages = pm.getInstalledPackagesAsUser(0, UserHandle.USER_SYSTEM);
    432         synchronized (this) {
    433             mInstalledPackages = packages;
    434         }
    435     }
    436 
    437     /**
    438      * Manages tasks that involve turning on/off the NFC controller.
    439      * <p/>
    440      * <p>All work that might turn the NFC adapter on or off must be done
    441      * through this task, to keep the handling of mState simple.
    442      * In other words, mState is only modified in these tasks (and we
    443      * don't need a lock to read it in these tasks).
    444      * <p/>
    445      * <p>These tasks are all done on the same AsyncTask background
    446      * thread, so they are serialized. Each task may temporarily transition
    447      * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in
    448      * either STATE_ON or STATE_OFF. This way each task can be guaranteed
    449      * of starting in either STATE_OFF or STATE_ON, without needing to hold
    450      * NfcService.this for the entire task.
    451      * <p/>
    452      * <p>AsyncTask's are also implicitly queued. This is useful for corner
    453      * cases like turning airplane mode on while TASK_ENABLE is in progress.
    454      * The TASK_DISABLE triggered by airplane mode will be correctly executed
    455      * immediately after TASK_ENABLE is complete. This seems like the most sane
    456      * way to deal with these situations.
    457      * <p/>
    458      * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing
    459      * preferences
    460      * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing
    461      * preferences
    462      * <p>{@link #TASK_BOOT} does first boot work and may enable NFC
    463      */
    464     class EnableDisableTask extends AsyncTask<Integer, Void, Void> {
    465         @Override
    466         protected Void doInBackground(Integer... params) {
    467             // Sanity check mState
    468             switch (mState) {
    469                 case NfcAdapter.STATE_TURNING_OFF:
    470                 case NfcAdapter.STATE_TURNING_ON:
    471                     Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " +
    472                             mState);
    473                     return null;
    474             }
    475 
    476             /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND,
    477              * override with the default. THREAD_PRIORITY_BACKGROUND causes
    478              * us to service software I2C too slow for firmware download
    479              * with the NXP PN544.
    480              * TODO: move this to the DAL I2C layer in libnfc-nxp, since this
    481              * problem only occurs on I2C platforms using PN544
    482              */
    483             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
    484 
    485             switch (params[0].intValue()) {
    486                 case TASK_ENABLE:
    487                     enableInternal();
    488                     break;
    489                 case TASK_DISABLE:
    490                     disableInternal();
    491                     break;
    492                 case TASK_BOOT:
    493                     Log.d(TAG, "checking on firmware download");
    494                     if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
    495                         Log.d(TAG, "NFC is on. Doing normal stuff");
    496                         enableInternal();
    497                     } else {
    498                         Log.d(TAG, "NFC is off.  Checking firmware version");
    499                         mDeviceHost.checkFirmware();
    500                     }
    501                     if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
    502                         Log.i(TAG, "First Boot");
    503                         mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
    504                         mPrefsEditor.apply();
    505                     }
    506                     break;
    507             }
    508 
    509             // Restore default AsyncTask priority
    510             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    511             return null;
    512         }
    513 
    514         /**
    515          * Enable NFC adapter functions.
    516          * Does not toggle preferences.
    517          */
    518         boolean enableInternal() {
    519             if (mState == NfcAdapter.STATE_ON) {
    520                 return true;
    521             }
    522             Log.i(TAG, "Enabling NFC");
    523             updateState(NfcAdapter.STATE_TURNING_ON);
    524 
    525             WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS);
    526             watchDog.start();
    527             try {
    528                 mRoutingWakeLock.acquire();
    529                 try {
    530                     if (!mDeviceHost.initialize()) {
    531                         Log.w(TAG, "Error enabling NFC");
    532                         updateState(NfcAdapter.STATE_OFF);
    533                         return false;
    534                     }
    535                 } finally {
    536                     mRoutingWakeLock.release();
    537                 }
    538             } finally {
    539                 watchDog.cancel();
    540             }
    541 
    542             if (mIsHceCapable) {
    543                 // Generate the initial card emulation routing table
    544                 mCardEmulationManager.onNfcEnabled();
    545             }
    546 
    547             synchronized (NfcService.this) {
    548                 mObjectMap.clear();
    549                 mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
    550                 updateState(NfcAdapter.STATE_ON);
    551             }
    552 
    553             initSoundPool();
    554 
    555             /* Start polling loop */
    556 
    557             applyRouting(true);
    558             return true;
    559         }
    560 
    561         /**
    562          * Disable all NFC adapter functions.
    563          * Does not toggle preferences.
    564          */
    565         boolean disableInternal() {
    566             if (mState == NfcAdapter.STATE_OFF) {
    567                 return true;
    568             }
    569             Log.i(TAG, "Disabling NFC");
    570             updateState(NfcAdapter.STATE_TURNING_OFF);
    571 
    572             /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog.
    573              * Implemented with a new thread (instead of a Handler or AsyncTask),
    574              * because the UI Thread and AsyncTask thread-pools can also get hung
    575              * when the NFC controller stops responding */
    576             WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS);
    577             watchDog.start();
    578 
    579             if (mIsHceCapable) {
    580                 mCardEmulationManager.onNfcDisabled();
    581             }
    582 
    583             mP2pLinkManager.enableDisable(false, false);
    584 
    585             // Stop watchdog if tag present
    586             // A convenient way to stop the watchdog properly consists of
    587             // disconnecting the tag. The polling loop shall be stopped before
    588             // to avoid the tag being discovered again.
    589             maybeDisconnectTarget();
    590 
    591             mNfcDispatcher.setForegroundDispatch(null, null, null);
    592 
    593 
    594             boolean result = mDeviceHost.deinitialize();
    595             if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result);
    596 
    597             watchDog.cancel();
    598 
    599             synchronized (NfcService.this) {
    600                 mCurrentDiscoveryParameters = NfcDiscoveryParameters.getNfcOffParameters();
    601                 updateState(NfcAdapter.STATE_OFF);
    602             }
    603 
    604             releaseSoundPool();
    605 
    606             return result;
    607         }
    608 
    609         void updateState(int newState) {
    610             synchronized (NfcService.this) {
    611                 if (newState == mState) {
    612                     return;
    613                 }
    614                 mState = newState;
    615                 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
    616                 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    617                 intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
    618                 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
    619             }
    620         }
    621     }
    622 
    623     void saveNfcOnSetting(boolean on) {
    624         synchronized (NfcService.this) {
    625             mPrefsEditor.putBoolean(PREF_NFC_ON, on);
    626             mPrefsEditor.apply();
    627         }
    628     }
    629 
    630     public void playSound(int sound) {
    631         synchronized (this) {
    632             if (mSoundPool == null) {
    633                 Log.w(TAG, "Not playing sound when NFC is disabled");
    634                 return;
    635             }
    636             switch (sound) {
    637                 case SOUND_START:
    638                     mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f);
    639                     break;
    640                 case SOUND_END:
    641                     mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f);
    642                     break;
    643                 case SOUND_ERROR:
    644                     mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f);
    645                     break;
    646             }
    647         }
    648     }
    649 
    650     synchronized int getUserId() {
    651         return mUserId;
    652     }
    653 
    654     void setBeamShareActivityState(boolean enabled) {
    655         UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    656         // Propagate the state change to all user profiles related to the current
    657         // user. Note that the list returned by getUserProfiles contains the
    658         // current user.
    659         List <UserHandle> luh = um.getUserProfiles();
    660         for (UserHandle uh : luh){
    661             enforceBeamShareActivityPolicy(mContext, uh, enabled);
    662         }
    663     }
    664 
    665     void enforceBeamShareActivityPolicy(Context context, UserHandle uh,
    666             boolean isGlobalEnabled){
    667         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    668         IPackageManager mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    669         boolean isActiveForUser =
    670                 (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) &&
    671                 isGlobalEnabled;
    672         if (DBG){
    673             Log.d(TAG, "Enforcing a policy change on user: " + uh +
    674                     ", isActiveForUser = " + isActiveForUser);
    675         }
    676         try {
    677             mIpm.setComponentEnabledSetting(new ComponentName(
    678                     BeamShareActivity.class.getPackageName$(),
    679                     BeamShareActivity.class.getName()),
    680                     isActiveForUser ?
    681                             PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
    682                             PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
    683                             PackageManager.DONT_KILL_APP,
    684                     uh.getIdentifier());
    685         } catch (RemoteException e) {
    686             Log.w(TAG, "Unable to change Beam status for user " + uh);
    687         }
    688     }
    689 
    690     final class NfcAdapterService extends INfcAdapter.Stub {
    691         @Override
    692         public boolean enable() throws RemoteException {
    693             NfcPermissions.enforceAdminPermissions(mContext);
    694 
    695             saveNfcOnSetting(true);
    696 
    697             new EnableDisableTask().execute(TASK_ENABLE);
    698 
    699             return true;
    700         }
    701 
    702         @Override
    703         public boolean disable(boolean saveState) throws RemoteException {
    704             NfcPermissions.enforceAdminPermissions(mContext);
    705 
    706             if (saveState) {
    707                 saveNfcOnSetting(false);
    708             }
    709 
    710             new EnableDisableTask().execute(TASK_DISABLE);
    711 
    712             return true;
    713         }
    714 
    715         @Override
    716         public void pausePolling(int timeoutInMs) {
    717             NfcPermissions.enforceAdminPermissions(mContext);
    718 
    719             if (timeoutInMs <= 0 || timeoutInMs > MAX_POLLING_PAUSE_TIMEOUT) {
    720                 Log.e(TAG, "Refusing to pause polling for " + timeoutInMs + "ms.");
    721                 return;
    722             }
    723 
    724             synchronized (NfcService.this) {
    725                 mPollingPaused = true;
    726                 mDeviceHost.disableDiscovery();
    727                 mHandler.sendMessageDelayed(
    728                         mHandler.obtainMessage(MSG_RESUME_POLLING), timeoutInMs);
    729             }
    730         }
    731 
    732         @Override
    733         public void resumePolling() {
    734             NfcPermissions.enforceAdminPermissions(mContext);
    735 
    736             synchronized (NfcService.this) {
    737                 if (!mPollingPaused) {
    738                     return;
    739                 }
    740 
    741                 mHandler.removeMessages(MSG_RESUME_POLLING);
    742                 mPollingPaused = false;
    743                 new ApplyRoutingTask().execute();
    744             }
    745         }
    746 
    747         @Override
    748         public boolean isNdefPushEnabled() throws RemoteException {
    749             synchronized (NfcService.this) {
    750                 return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled;
    751             }
    752         }
    753 
    754         @Override
    755         public boolean enableNdefPush() throws RemoteException {
    756             NfcPermissions.enforceAdminPermissions(mContext);
    757             synchronized (NfcService.this) {
    758                 if (mIsNdefPushEnabled) {
    759                     return true;
    760                 }
    761                 Log.i(TAG, "enabling NDEF Push");
    762                 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true);
    763                 mPrefsEditor.apply();
    764                 mIsNdefPushEnabled = true;
    765                 setBeamShareActivityState(true);
    766                 if (isNfcEnabled()) {
    767                     mP2pLinkManager.enableDisable(true, true);
    768                 }
    769             }
    770             return true;
    771         }
    772 
    773         @Override
    774         public boolean disableNdefPush() throws RemoteException {
    775             NfcPermissions.enforceAdminPermissions(mContext);
    776             synchronized (NfcService.this) {
    777                 if (!mIsNdefPushEnabled) {
    778                     return true;
    779                 }
    780                 Log.i(TAG, "disabling NDEF Push");
    781                 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false);
    782                 mPrefsEditor.apply();
    783                 mIsNdefPushEnabled = false;
    784                 setBeamShareActivityState(false);
    785                 if (isNfcEnabled()) {
    786                     mP2pLinkManager.enableDisable(false, true);
    787                 }
    788             }
    789             return true;
    790         }
    791 
    792         @Override
    793         public void setForegroundDispatch(PendingIntent intent,
    794                 IntentFilter[] filters, TechListParcel techListsParcel) {
    795             NfcPermissions.enforceUserPermissions(mContext);
    796             if (!mForegroundUtils.isInForeground(Binder.getCallingUid())) {
    797                 Log.e(TAG, "setForegroundDispatch: Caller not in foreground.");
    798                 return;
    799             }
    800             // Short-cut the disable path
    801             if (intent == null && filters == null && techListsParcel == null) {
    802                 mNfcDispatcher.setForegroundDispatch(null, null, null);
    803                 return;
    804             }
    805 
    806             // Validate the IntentFilters
    807             if (filters != null) {
    808                 if (filters.length == 0) {
    809                     filters = null;
    810                 } else {
    811                     for (IntentFilter filter : filters) {
    812                         if (filter == null) {
    813                             throw new IllegalArgumentException("null IntentFilter");
    814                         }
    815                     }
    816                 }
    817             }
    818 
    819             // Validate the tech lists
    820             String[][] techLists = null;
    821             if (techListsParcel != null) {
    822                 techLists = techListsParcel.getTechLists();
    823             }
    824 
    825             mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
    826         }
    827 
    828 
    829         @Override
    830         public void setAppCallback(IAppCallback callback) {
    831             NfcPermissions.enforceUserPermissions(mContext);
    832 
    833             // don't allow Beam for managed profiles, or devices with a device owner or policy owner
    834             UserInfo userInfo = mUserManager.getUserInfo(UserHandle.getCallingUserId());
    835             if(!mUserManager.hasUserRestriction(
    836                             UserManager.DISALLOW_OUTGOING_BEAM, userInfo.getUserHandle())) {
    837                 mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid());
    838             } else if (DBG) {
    839                 Log.d(TAG, "Disabling default Beam behavior");
    840             }
    841         }
    842 
    843         @Override
    844         public boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback)
    845                 throws RemoteException {
    846             NfcPermissions.enforceUserPermissions(mContext);
    847 
    848             TagEndpoint tag = (TagEndpoint) findAndRemoveObject(nativeHandle);
    849             if (tag != null) {
    850                 // Store UID and params
    851                 int uidLength = tag.getUid().length;
    852                 synchronized (NfcService.this) {
    853                     mDebounceTagDebounceMs = debounceMs;
    854                     mDebounceTagUid = new byte[uidLength];
    855                     mDebounceTagRemovedCallback = callback;
    856                     System.arraycopy(tag.getUid(), 0, mDebounceTagUid, 0, uidLength);
    857                 }
    858 
    859                 // Disconnect from this tag; this should resume the normal
    860                 // polling loop (and enter listen mode for a while), before
    861                 // we pick up any tags again.
    862                 tag.disconnect();
    863                 mHandler.sendEmptyMessageDelayed(MSG_TAG_DEBOUNCE, debounceMs);
    864                 return true;
    865             } else {
    866                 return false;
    867             }
    868         }
    869 
    870         @Override
    871         public void verifyNfcPermission() {
    872             NfcPermissions.enforceUserPermissions(mContext);
    873         }
    874 
    875         @Override
    876         public void invokeBeam() {
    877             NfcPermissions.enforceUserPermissions(mContext);
    878 
    879             if (mForegroundUtils.isInForeground(Binder.getCallingUid())) {
    880                 mP2pLinkManager.onManualBeamInvoke(null);
    881             } else {
    882                 Log.e(TAG, "Calling activity not in foreground.");
    883             }
    884         }
    885 
    886         @Override
    887         public void invokeBeamInternal(BeamShareData shareData) {
    888             NfcPermissions.enforceAdminPermissions(mContext);
    889             Message msg = Message.obtain();
    890             msg.what = MSG_INVOKE_BEAM;
    891             msg.obj = shareData;
    892             // We have to send this message delayed for two reasons:
    893             // 1) This is an IPC call from BeamShareActivity, which is
    894             //    running when the user has invoked Beam through the
    895             //    share menu. As soon as BeamShareActivity closes, the UI
    896             //    will need some time to rebuild the original Activity.
    897             //    Waiting here for a while gives a better chance of the UI
    898             //    having been rebuilt, which means the screenshot that the
    899             //    Beam animation is using will be more accurate.
    900             // 2) Similarly, because the Activity that launched BeamShareActivity
    901             //    with an ACTION_SEND intent is now in paused state, the NDEF
    902             //    callbacks that it has registered may no longer be valid.
    903             //    Allowing the original Activity to resume will make sure we
    904             //    it has a chance to re-register the NDEF message / callback,
    905             //    so we share the right data.
    906             //
    907             //    Note that this is somewhat of a hack because the delay may not actually
    908             //    be long enough for 2) on very slow devices, but there's no better
    909             //    way to do this right now without additional framework changes.
    910             mHandler.sendMessageDelayed(msg, INVOKE_BEAM_DELAY_MS);
    911         }
    912 
    913         @Override
    914         public INfcTag getNfcTagInterface() throws RemoteException {
    915             return mNfcTagService;
    916         }
    917 
    918         @Override
    919         public INfcCardEmulation getNfcCardEmulationInterface() {
    920             if (mIsHceCapable) {
    921                 return mCardEmulationManager.getNfcCardEmulationInterface();
    922             } else {
    923                 return null;
    924             }
    925         }
    926 
    927         @Override
    928         public INfcFCardEmulation getNfcFCardEmulationInterface() {
    929             if (mIsHceFCapable) {
    930                 return mCardEmulationManager.getNfcFCardEmulationInterface();
    931             } else {
    932                 return null;
    933             }
    934         }
    935 
    936         @Override
    937         public int getState() throws RemoteException {
    938             synchronized (NfcService.this) {
    939                 return mState;
    940             }
    941         }
    942 
    943         @Override
    944         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    945             NfcService.this.dump(fd, pw, args);
    946         }
    947 
    948         @Override
    949         public void dispatch(Tag tag) throws RemoteException {
    950             NfcPermissions.enforceAdminPermissions(mContext);
    951             mNfcDispatcher.dispatchTag(tag);
    952         }
    953 
    954         @Override
    955         public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
    956             NfcPermissions.enforceAdminPermissions(mContext);
    957             mDeviceHost.setP2pInitiatorModes(initiatorModes);
    958             mDeviceHost.setP2pTargetModes(targetModes);
    959             applyRouting(true);
    960         }
    961 
    962         @Override
    963         public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras)
    964                 throws RemoteException {
    965             int callingUid = Binder.getCallingUid();
    966             if (callingUid != Process.SYSTEM_UID && !mForegroundUtils.isInForeground(callingUid)) {
    967                 Log.e(TAG, "setReaderMode: Caller is not in foreground and is not system process.");
    968                 return;
    969             }
    970             synchronized (NfcService.this) {
    971                 if (!isNfcEnabled()) {
    972                     Log.e(TAG, "setReaderMode() called while NFC is not enabled.");
    973                     return;
    974                 }
    975                 if (flags != 0) {
    976                     try {
    977                         mReaderModeParams = new ReaderModeParams();
    978                         mReaderModeParams.callback = callback;
    979                         mReaderModeParams.flags = flags;
    980                         mReaderModeParams.presenceCheckDelay = extras != null
    981                                 ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY,
    982                                         DEFAULT_PRESENCE_CHECK_DELAY))
    983                                 : DEFAULT_PRESENCE_CHECK_DELAY;
    984                         binder.linkToDeath(mReaderModeDeathRecipient, 0);
    985                     } catch (RemoteException e) {
    986                         Log.e(TAG, "Remote binder has already died.");
    987                         return;
    988                     }
    989                 } else {
    990                     try {
    991                         mReaderModeParams = null;
    992                         binder.unlinkToDeath(mReaderModeDeathRecipient, 0);
    993                     } catch (NoSuchElementException e) {
    994                         Log.e(TAG, "Reader mode Binder was never registered.");
    995                     }
    996                 }
    997                 applyRouting(false);
    998             }
    999         }
   1000 
   1001         @Override
   1002         public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) throws RemoteException {
   1003             // nfc-extras implementation is no longer present in AOSP.
   1004             return null;
   1005         }
   1006 
   1007         @Override
   1008         public void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, int[] techList) {
   1009             NfcPermissions.enforceAdminPermissions(mContext);
   1010 
   1011             int lockscreenPollMask = computeLockscreenPollMask(techList);
   1012             synchronized (NfcService.this) {
   1013                 mNfcUnlockManager.addUnlockHandler(unlockHandler, lockscreenPollMask);
   1014             }
   1015 
   1016             applyRouting(false);
   1017         }
   1018 
   1019         @Override
   1020         public void removeNfcUnlockHandler(INfcUnlockHandler token) throws RemoteException {
   1021             synchronized (NfcService.this) {
   1022                 mNfcUnlockManager.removeUnlockHandler(token.asBinder());
   1023             }
   1024 
   1025             applyRouting(false);
   1026         }
   1027 
   1028         private int computeLockscreenPollMask(int[] techList) {
   1029 
   1030             Map<Integer, Integer> techCodeToMask = new HashMap<Integer, Integer>();
   1031 
   1032             techCodeToMask.put(TagTechnology.NFC_A, NfcService.NFC_POLL_A);
   1033             techCodeToMask.put(TagTechnology.NFC_B, NfcService.NFC_POLL_B);
   1034             techCodeToMask.put(TagTechnology.NFC_V, NfcService.NFC_POLL_ISO15693);
   1035             techCodeToMask.put(TagTechnology.NFC_F, NfcService.NFC_POLL_F);
   1036             techCodeToMask.put(TagTechnology.NFC_BARCODE, NfcService.NFC_POLL_KOVIO);
   1037 
   1038             int mask = 0;
   1039 
   1040             for (int i = 0; i < techList.length; i++) {
   1041                 if (techCodeToMask.containsKey(techList[i])) {
   1042                     mask |= techCodeToMask.get(techList[i]).intValue();
   1043                 }
   1044             }
   1045 
   1046             return mask;
   1047         }
   1048     }
   1049 
   1050     final class ReaderModeDeathRecipient implements IBinder.DeathRecipient {
   1051         @Override
   1052         public void binderDied() {
   1053             synchronized (NfcService.this) {
   1054                 if (mReaderModeParams != null) {
   1055                     mReaderModeParams = null;
   1056                     applyRouting(false);
   1057                 }
   1058             }
   1059         }
   1060     }
   1061 
   1062     final class TagService extends INfcTag.Stub {
   1063         @Override
   1064         public int connect(int nativeHandle, int technology) throws RemoteException {
   1065             NfcPermissions.enforceUserPermissions(mContext);
   1066 
   1067             TagEndpoint tag = null;
   1068 
   1069             if (!isNfcEnabled()) {
   1070                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1071             }
   1072 
   1073             /* find the tag in the hmap */
   1074             tag = (TagEndpoint) findObject(nativeHandle);
   1075             if (tag == null) {
   1076                 return ErrorCodes.ERROR_DISCONNECT;
   1077             }
   1078 
   1079             if (!tag.isPresent()) {
   1080                 return ErrorCodes.ERROR_DISCONNECT;
   1081             }
   1082 
   1083             // Note that on most tags, all technologies are behind a single
   1084             // handle. This means that the connect at the lower levels
   1085             // will do nothing, as the tag is already connected to that handle.
   1086             if (tag.connect(technology)) {
   1087                 return ErrorCodes.SUCCESS;
   1088             } else {
   1089                 return ErrorCodes.ERROR_DISCONNECT;
   1090             }
   1091         }
   1092 
   1093         @Override
   1094         public int reconnect(int nativeHandle) throws RemoteException {
   1095             NfcPermissions.enforceUserPermissions(mContext);
   1096 
   1097             TagEndpoint tag = null;
   1098 
   1099             // Check if NFC is enabled
   1100             if (!isNfcEnabled()) {
   1101                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1102             }
   1103 
   1104             /* find the tag in the hmap */
   1105             tag = (TagEndpoint) findObject(nativeHandle);
   1106             if (tag != null) {
   1107                 if (tag.reconnect()) {
   1108                     return ErrorCodes.SUCCESS;
   1109                 } else {
   1110                     return ErrorCodes.ERROR_DISCONNECT;
   1111                 }
   1112             }
   1113             return ErrorCodes.ERROR_DISCONNECT;
   1114         }
   1115 
   1116         @Override
   1117         public int[] getTechList(int nativeHandle) throws RemoteException {
   1118             NfcPermissions.enforceUserPermissions(mContext);
   1119 
   1120             // Check if NFC is enabled
   1121             if (!isNfcEnabled()) {
   1122                 return null;
   1123             }
   1124 
   1125             /* find the tag in the hmap */
   1126             TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
   1127             if (tag != null) {
   1128                 return tag.getTechList();
   1129             }
   1130             return null;
   1131         }
   1132 
   1133         @Override
   1134         public boolean isPresent(int nativeHandle) throws RemoteException {
   1135             TagEndpoint tag = null;
   1136 
   1137             // Check if NFC is enabled
   1138             if (!isNfcEnabled()) {
   1139                 return false;
   1140             }
   1141 
   1142             /* find the tag in the hmap */
   1143             tag = (TagEndpoint) findObject(nativeHandle);
   1144             if (tag == null) {
   1145                 return false;
   1146             }
   1147 
   1148             return tag.isPresent();
   1149         }
   1150 
   1151         @Override
   1152         public boolean isNdef(int nativeHandle) throws RemoteException {
   1153             NfcPermissions.enforceUserPermissions(mContext);
   1154 
   1155             TagEndpoint tag = null;
   1156 
   1157             // Check if NFC is enabled
   1158             if (!isNfcEnabled()) {
   1159                 return false;
   1160             }
   1161 
   1162             /* find the tag in the hmap */
   1163             tag = (TagEndpoint) findObject(nativeHandle);
   1164             int[] ndefInfo = new int[2];
   1165             if (tag == null) {
   1166                 return false;
   1167             }
   1168             return tag.checkNdef(ndefInfo);
   1169         }
   1170 
   1171         @Override
   1172         public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
   1173                 throws RemoteException {
   1174             NfcPermissions.enforceUserPermissions(mContext);
   1175 
   1176             TagEndpoint tag = null;
   1177             byte[] response;
   1178 
   1179             // Check if NFC is enabled
   1180             if (!isNfcEnabled()) {
   1181                 return null;
   1182             }
   1183 
   1184             /* find the tag in the hmap */
   1185             tag = (TagEndpoint) findObject(nativeHandle);
   1186             if (tag != null) {
   1187                 // Check if length is within limits
   1188                 if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
   1189                     return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
   1190                 }
   1191                 int[] targetLost = new int[1];
   1192                 response = tag.transceive(data, raw, targetLost);
   1193                 int result;
   1194                 if (response != null) {
   1195                     result = TransceiveResult.RESULT_SUCCESS;
   1196                 } else if (targetLost[0] == 1) {
   1197                     result = TransceiveResult.RESULT_TAGLOST;
   1198                 } else {
   1199                     result = TransceiveResult.RESULT_FAILURE;
   1200                 }
   1201                 return new TransceiveResult(result, response);
   1202             }
   1203             return null;
   1204         }
   1205 
   1206         @Override
   1207         public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
   1208             NfcPermissions.enforceUserPermissions(mContext);
   1209 
   1210             TagEndpoint tag;
   1211 
   1212             // Check if NFC is enabled
   1213             if (!isNfcEnabled()) {
   1214                 return null;
   1215             }
   1216 
   1217             /* find the tag in the hmap */
   1218             tag = (TagEndpoint) findObject(nativeHandle);
   1219             if (tag != null) {
   1220                 byte[] buf = tag.readNdef();
   1221                 if (buf == null) {
   1222                     return null;
   1223                 }
   1224 
   1225                 /* Create an NdefMessage */
   1226                 try {
   1227                     return new NdefMessage(buf);
   1228                 } catch (FormatException e) {
   1229                     return null;
   1230                 }
   1231             }
   1232             return null;
   1233         }
   1234 
   1235         @Override
   1236         public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
   1237             NfcPermissions.enforceUserPermissions(mContext);
   1238 
   1239             TagEndpoint tag;
   1240 
   1241             // Check if NFC is enabled
   1242             if (!isNfcEnabled()) {
   1243                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1244             }
   1245 
   1246             /* find the tag in the hmap */
   1247             tag = (TagEndpoint) findObject(nativeHandle);
   1248             if (tag == null) {
   1249                 return ErrorCodes.ERROR_IO;
   1250             }
   1251 
   1252             if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM;
   1253 
   1254             if (tag.writeNdef(msg.toByteArray())) {
   1255                 return ErrorCodes.SUCCESS;
   1256             } else {
   1257                 return ErrorCodes.ERROR_IO;
   1258             }
   1259 
   1260         }
   1261 
   1262         @Override
   1263         public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
   1264             throw new UnsupportedOperationException();
   1265         }
   1266 
   1267         @Override
   1268         public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
   1269             NfcPermissions.enforceUserPermissions(mContext);
   1270 
   1271             TagEndpoint tag;
   1272 
   1273             // Check if NFC is enabled
   1274             if (!isNfcEnabled()) {
   1275                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1276             }
   1277 
   1278             /* find the tag in the hmap */
   1279             tag = (TagEndpoint) findObject(nativeHandle);
   1280             if (tag == null) {
   1281                 return ErrorCodes.ERROR_IO;
   1282             }
   1283 
   1284             if (tag.makeReadOnly()) {
   1285                 return ErrorCodes.SUCCESS;
   1286             } else {
   1287                 return ErrorCodes.ERROR_IO;
   1288             }
   1289         }
   1290 
   1291         @Override
   1292         public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
   1293             NfcPermissions.enforceUserPermissions(mContext);
   1294 
   1295             TagEndpoint tag;
   1296 
   1297             // Check if NFC is enabled
   1298             if (!isNfcEnabled()) {
   1299                 return ErrorCodes.ERROR_NOT_INITIALIZED;
   1300             }
   1301 
   1302             /* find the tag in the hmap */
   1303             tag = (TagEndpoint) findObject(nativeHandle);
   1304             if (tag == null) {
   1305                 return ErrorCodes.ERROR_IO;
   1306             }
   1307 
   1308             if (tag.formatNdef(key)) {
   1309                 return ErrorCodes.SUCCESS;
   1310             } else {
   1311                 return ErrorCodes.ERROR_IO;
   1312             }
   1313         }
   1314 
   1315         @Override
   1316         public Tag rediscover(int nativeHandle) throws RemoteException {
   1317             NfcPermissions.enforceUserPermissions(mContext);
   1318 
   1319             TagEndpoint tag = null;
   1320 
   1321             // Check if NFC is enabled
   1322             if (!isNfcEnabled()) {
   1323                 return null;
   1324             }
   1325 
   1326             /* find the tag in the hmap */
   1327             tag = (TagEndpoint) findObject(nativeHandle);
   1328             if (tag != null) {
   1329                 // For now the prime usecase for rediscover() is to be able
   1330                 // to access the NDEF technology after formatting without
   1331                 // having to remove the tag from the field, or similar
   1332                 // to have access to NdefFormatable in case low-level commands
   1333                 // were used to remove NDEF. So instead of doing a full stack
   1334                 // rediscover (which is poorly supported at the moment anyway),
   1335                 // we simply remove these two technologies and detect them
   1336                 // again.
   1337                 tag.removeTechnology(TagTechnology.NDEF);
   1338                 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
   1339                 tag.findAndReadNdef();
   1340                 // Build a new Tag object to return
   1341                 Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
   1342                         tag.getTechExtras(), tag.getHandle(), this);
   1343                 return newTag;
   1344             }
   1345             return null;
   1346         }
   1347 
   1348         @Override
   1349         public int setTimeout(int tech, int timeout) throws RemoteException {
   1350             NfcPermissions.enforceUserPermissions(mContext);
   1351             boolean success = mDeviceHost.setTimeout(tech, timeout);
   1352             if (success) {
   1353                 return ErrorCodes.SUCCESS;
   1354             } else {
   1355                 return ErrorCodes.ERROR_INVALID_PARAM;
   1356             }
   1357         }
   1358 
   1359         @Override
   1360         public int getTimeout(int tech) throws RemoteException {
   1361             NfcPermissions.enforceUserPermissions(mContext);
   1362 
   1363             return mDeviceHost.getTimeout(tech);
   1364         }
   1365 
   1366         @Override
   1367         public void resetTimeouts() throws RemoteException {
   1368             NfcPermissions.enforceUserPermissions(mContext);
   1369 
   1370             mDeviceHost.resetTimeouts();
   1371         }
   1372 
   1373         @Override
   1374         public boolean canMakeReadOnly(int ndefType) throws RemoteException {
   1375             return mDeviceHost.canMakeReadOnly(ndefType);
   1376         }
   1377 
   1378         @Override
   1379         public int getMaxTransceiveLength(int tech) throws RemoteException {
   1380             return mDeviceHost.getMaxTransceiveLength(tech);
   1381         }
   1382 
   1383         @Override
   1384         public boolean getExtendedLengthApdusSupported() throws RemoteException {
   1385             return mDeviceHost.getExtendedLengthApdusSupported();
   1386         }
   1387     }
   1388 
   1389     boolean isNfcEnabledOrShuttingDown() {
   1390         synchronized (this) {
   1391             return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF);
   1392         }
   1393     }
   1394 
   1395     boolean isNfcEnabled() {
   1396         synchronized (this) {
   1397             return mState == NfcAdapter.STATE_ON;
   1398         }
   1399     }
   1400 
   1401     class WatchDogThread extends Thread {
   1402         final Object mCancelWaiter = new Object();
   1403         final int mTimeout;
   1404         boolean mCanceled = false;
   1405 
   1406         public WatchDogThread(String threadName, int timeout) {
   1407             super(threadName);
   1408             mTimeout = timeout;
   1409         }
   1410 
   1411         @Override
   1412         public void run() {
   1413             try {
   1414                 synchronized (mCancelWaiter) {
   1415                     mCancelWaiter.wait(mTimeout);
   1416                     if (mCanceled) {
   1417                         return;
   1418                     }
   1419                 }
   1420             } catch (InterruptedException e) {
   1421                 // Should not happen; fall-through to abort.
   1422                 Log.w(TAG, "Watchdog thread interruped.");
   1423                 interrupt();
   1424             }
   1425             Log.e(TAG, "Watchdog triggered, aborting.");
   1426             mDeviceHost.doAbort();
   1427         }
   1428 
   1429         public synchronized void cancel() {
   1430             synchronized (mCancelWaiter) {
   1431                 mCanceled = true;
   1432                 mCancelWaiter.notify();
   1433             }
   1434         }
   1435     }
   1436 
   1437     static byte[] hexStringToBytes(String s) {
   1438         if (s == null || s.length() == 0) return null;
   1439         int len = s.length();
   1440         if (len % 2 != 0) {
   1441             s = '0' + s;
   1442             len++;
   1443         }
   1444         byte[] data = new byte[len / 2];
   1445         for (int i = 0; i < len; i += 2) {
   1446             data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
   1447                     + Character.digit(s.charAt(i + 1), 16));
   1448         }
   1449         return data;
   1450     }
   1451 
   1452     /**
   1453      * Read mScreenState and apply NFC-C polling and NFC-EE routing
   1454      */
   1455     void applyRouting(boolean force) {
   1456         synchronized (this) {
   1457             if (!isNfcEnabledOrShuttingDown()) {
   1458                 return;
   1459             }
   1460             WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS);
   1461             if (mInProvisionMode) {
   1462                 mInProvisionMode = Settings.Secure.getInt(mContentResolver,
   1463                         Settings.Global.DEVICE_PROVISIONED, 0) == 0;
   1464                 if (!mInProvisionMode) {
   1465                     // Notify dispatcher it's fine to dispatch to any package now
   1466                     // and allow handover transfers.
   1467                     mNfcDispatcher.disableProvisioningMode();
   1468                 }
   1469             }
   1470             // Special case: if we're transitioning to unlocked state while
   1471             // still talking to a tag, postpone re-configuration.
   1472             if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && isTagPresent()) {
   1473                 Log.d(TAG, "Not updating discovery parameters, tag connected.");
   1474                 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RESUME_POLLING),
   1475                         APPLY_ROUTING_RETRY_TIMEOUT_MS);
   1476                 return;
   1477             }
   1478 
   1479             try {
   1480                 watchDog.start();
   1481                 // Compute new polling parameters
   1482                 NfcDiscoveryParameters newParams = computeDiscoveryParameters(mScreenState);
   1483                 if (force || !newParams.equals(mCurrentDiscoveryParameters)) {
   1484                     if (newParams.shouldEnableDiscovery()) {
   1485                         boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
   1486                         mDeviceHost.enableDiscovery(newParams, shouldRestart);
   1487                     } else {
   1488                         mDeviceHost.disableDiscovery();
   1489                     }
   1490                     mCurrentDiscoveryParameters = newParams;
   1491                 } else {
   1492                     Log.d(TAG, "Discovery configuration equal, not updating.");
   1493                 }
   1494             } finally {
   1495                 watchDog.cancel();
   1496             }
   1497         }
   1498     }
   1499 
   1500     private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) {
   1501         // Recompute discovery parameters based on screen state
   1502         NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder();
   1503         // Polling
   1504         if (screenState >= NFC_POLLING_MODE) {
   1505             // Check if reader-mode is enabled
   1506             if (mReaderModeParams != null) {
   1507                 int techMask = 0;
   1508                 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0)
   1509                     techMask |= NFC_POLL_A;
   1510                 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0)
   1511                     techMask |= NFC_POLL_B;
   1512                 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0)
   1513                     techMask |= NFC_POLL_F;
   1514                 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0)
   1515                     techMask |= NFC_POLL_ISO15693;
   1516                 if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0)
   1517                     techMask |= NFC_POLL_KOVIO;
   1518 
   1519                 paramsBuilder.setTechMask(techMask);
   1520                 paramsBuilder.setEnableReaderMode(true);
   1521             } else {
   1522                 paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
   1523                 paramsBuilder.setEnableP2p(mIsNdefPushEnabled);
   1524             }
   1525         } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) {
   1526             paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
   1527             // enable P2P for MFM/EDU/Corp provisioning
   1528             paramsBuilder.setEnableP2p(true);
   1529         } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED &&
   1530                 mNfcUnlockManager.isLockscreenPollingEnabled()) {
   1531             // For lock-screen tags, no low-power polling
   1532             paramsBuilder.setTechMask(mNfcUnlockManager.getLockscreenPollMask());
   1533             paramsBuilder.setEnableLowPowerDiscovery(false);
   1534             paramsBuilder.setEnableP2p(false);
   1535         }
   1536 
   1537         if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
   1538             // Host routing is always enabled at lock screen or later
   1539             paramsBuilder.setEnableHostRouting(true);
   1540         }
   1541 
   1542         return paramsBuilder.build();
   1543     }
   1544 
   1545     private boolean isTagPresent() {
   1546         for (Object object : mObjectMap.values()) {
   1547             if (object instanceof TagEndpoint) {
   1548                 return ((TagEndpoint) object).isPresent();
   1549             }
   1550         }
   1551         return false;
   1552     }
   1553     /**
   1554      * Disconnect any target if present
   1555      */
   1556     void maybeDisconnectTarget() {
   1557         if (!isNfcEnabledOrShuttingDown()) {
   1558             return;
   1559         }
   1560         Object[] objectsToDisconnect;
   1561         synchronized (this) {
   1562             Object[] objectValues = mObjectMap.values().toArray();
   1563             // Copy the array before we clear mObjectMap,
   1564             // just in case the HashMap values are backed by the same array
   1565             objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length);
   1566             mObjectMap.clear();
   1567         }
   1568         for (Object o : objectsToDisconnect) {
   1569             if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName());
   1570             if (o instanceof TagEndpoint) {
   1571                 // Disconnect from tags
   1572                 TagEndpoint tag = (TagEndpoint) o;
   1573                 tag.disconnect();
   1574             } else if (o instanceof NfcDepEndpoint) {
   1575                 // Disconnect from P2P devices
   1576                 NfcDepEndpoint device = (NfcDepEndpoint) o;
   1577                 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
   1578                     // Remote peer is target, request disconnection
   1579                     device.disconnect();
   1580                 } else {
   1581                     // Remote peer is initiator, we cannot disconnect
   1582                     // Just wait for field removal
   1583                 }
   1584             }
   1585         }
   1586     }
   1587 
   1588     Object findObject(int key) {
   1589         synchronized (this) {
   1590             Object device = mObjectMap.get(key);
   1591             if (device == null) {
   1592                 Log.w(TAG, "Handle not found");
   1593             }
   1594             return device;
   1595         }
   1596     }
   1597 
   1598     Object findAndRemoveObject(int handle) {
   1599         synchronized (this) {
   1600             Object device = mObjectMap.get(handle);
   1601             if (device == null) {
   1602                 Log.w(TAG, "Handle not found");
   1603             } else {
   1604                 mObjectMap.remove(handle);
   1605             }
   1606             return device;
   1607         }
   1608     }
   1609 
   1610     void registerTagObject(TagEndpoint tag) {
   1611         synchronized (this) {
   1612             mObjectMap.put(tag.getHandle(), tag);
   1613         }
   1614     }
   1615 
   1616     void unregisterObject(int handle) {
   1617         synchronized (this) {
   1618             mObjectMap.remove(handle);
   1619         }
   1620     }
   1621 
   1622     /**
   1623      * For use by code in this process
   1624      */
   1625     public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
   1626             throws LlcpException {
   1627         return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength);
   1628     }
   1629 
   1630     /**
   1631      * For use by code in this process
   1632      */
   1633     public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn)
   1634             throws LlcpException {
   1635         return mDeviceHost.createLlcpConnectionlessSocket(sap, sn);
   1636     }
   1637 
   1638     /**
   1639      * For use by code in this process
   1640      */
   1641     public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw,
   1642             int linearBufferLength) throws LlcpException {
   1643         return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength);
   1644     }
   1645 
   1646     public void sendMockNdefTag(NdefMessage msg) {
   1647         sendMessage(MSG_MOCK_NDEF, msg);
   1648     }
   1649 
   1650     public void routeAids(String aid, int route) {
   1651         Message msg = mHandler.obtainMessage();
   1652         msg.what = MSG_ROUTE_AID;
   1653         msg.arg1 = route;
   1654         msg.obj = aid;
   1655         mHandler.sendMessage(msg);
   1656     }
   1657 
   1658     public void unrouteAids(String aid) {
   1659         sendMessage(MSG_UNROUTE_AID, aid);
   1660     }
   1661 
   1662     private byte[] getT3tIdentifierBytes(String systemCode, String nfcId2) {
   1663         ByteBuffer buffer = ByteBuffer.allocate(2 + 8);
   1664         buffer.put(hexStringToBytes(systemCode));
   1665         buffer.put(hexStringToBytes(nfcId2));
   1666 
   1667         byte[] t3tIdBytes = new byte[buffer.position()];
   1668         buffer.position(0);
   1669         buffer.get(t3tIdBytes);
   1670 
   1671         return t3tIdBytes;
   1672     }
   1673 
   1674     public void registerT3tIdentifier(String systemCode, String nfcId2) {
   1675         Log.d(TAG, "request to register LF_T3T_IDENTIFIER");
   1676 
   1677         byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2);
   1678         sendMessage(MSG_REGISTER_T3T_IDENTIFIER, t3tIdentifier);
   1679     }
   1680 
   1681     public void deregisterT3tIdentifier(String systemCode, String nfcId2) {
   1682         Log.d(TAG, "request to deregister LF_T3T_IDENTIFIER");
   1683 
   1684         byte[] t3tIdentifier = getT3tIdentifierBytes(systemCode, nfcId2);
   1685         sendMessage(MSG_DEREGISTER_T3T_IDENTIFIER, t3tIdentifier);
   1686     }
   1687 
   1688     public void clearT3tIdentifiersCache() {
   1689         Log.d(TAG, "clear T3t Identifiers Cache");
   1690         mDeviceHost.clearT3tIdentifiersCache();
   1691     }
   1692 
   1693     public int getLfT3tMax() {
   1694         return mDeviceHost.getLfT3tMax();
   1695     }
   1696 
   1697     public void commitRouting() {
   1698         mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING);
   1699     }
   1700 
   1701     public boolean sendData(byte[] data) {
   1702         return mDeviceHost.sendRawFrame(data);
   1703     }
   1704 
   1705     void sendMessage(int what, Object obj) {
   1706         Message msg = mHandler.obtainMessage();
   1707         msg.what = what;
   1708         msg.obj = obj;
   1709         mHandler.sendMessage(msg);
   1710     }
   1711 
   1712     final class NfcServiceHandler extends Handler {
   1713         @Override
   1714         public void handleMessage(Message msg) {
   1715             switch (msg.what) {
   1716                 case MSG_ROUTE_AID: {
   1717                     int route = msg.arg1;
   1718                     String aid = (String) msg.obj;
   1719                     mDeviceHost.routeAid(hexStringToBytes(aid), route);
   1720                     // Restart polling config
   1721                     break;
   1722                 }
   1723                 case MSG_UNROUTE_AID: {
   1724                     String aid = (String) msg.obj;
   1725                     mDeviceHost.unrouteAid(hexStringToBytes(aid));
   1726                     break;
   1727                 }
   1728                 case MSG_REGISTER_T3T_IDENTIFIER: {
   1729                     Log.d(TAG, "message to register LF_T3T_IDENTIFIER");
   1730                     mDeviceHost.disableDiscovery();
   1731 
   1732                     byte[] t3tIdentifier = (byte[]) msg.obj;
   1733                     mDeviceHost.registerT3tIdentifier(t3tIdentifier);
   1734 
   1735                     NfcDiscoveryParameters params = computeDiscoveryParameters(mScreenState);
   1736                     boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
   1737                     mDeviceHost.enableDiscovery(params, shouldRestart);
   1738                     break;
   1739                 }
   1740                 case MSG_DEREGISTER_T3T_IDENTIFIER: {
   1741                     Log.d(TAG, "message to deregister LF_T3T_IDENTIFIER");
   1742                     mDeviceHost.disableDiscovery();
   1743 
   1744                     byte[] t3tIdentifier = (byte[]) msg.obj;
   1745                     mDeviceHost.deregisterT3tIdentifier(t3tIdentifier);
   1746 
   1747                     NfcDiscoveryParameters params = computeDiscoveryParameters(mScreenState);
   1748                     boolean shouldRestart = mCurrentDiscoveryParameters.shouldEnableDiscovery();
   1749                     mDeviceHost.enableDiscovery(params, shouldRestart);
   1750                     break;
   1751                 }
   1752                 case MSG_INVOKE_BEAM: {
   1753                     mP2pLinkManager.onManualBeamInvoke((BeamShareData)msg.obj);
   1754                     break;
   1755                 }
   1756                 case MSG_COMMIT_ROUTING: {
   1757                     boolean commit = false;
   1758                     synchronized (NfcService.this) {
   1759                         if (mCurrentDiscoveryParameters.shouldEnableDiscovery()) {
   1760                             commit = true;
   1761                         } else {
   1762                             Log.d(TAG, "Not committing routing because discovery is disabled.");
   1763                         }
   1764                     }
   1765                     if (commit) {
   1766                         mDeviceHost.commitRouting();
   1767                     }
   1768                     break;
   1769                 }
   1770                 case MSG_MOCK_NDEF: {
   1771                     NdefMessage ndefMsg = (NdefMessage) msg.obj;
   1772                     Bundle extras = new Bundle();
   1773                     extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg);
   1774                     extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0);
   1775                     extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY);
   1776                     extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER);
   1777                     Tag tag = Tag.createMockTag(new byte[]{0x00},
   1778                             new int[]{TagTechnology.NDEF},
   1779                             new Bundle[]{extras});
   1780                     Log.d(TAG, "mock NDEF tag, starting corresponding activity");
   1781                     Log.d(TAG, tag.toString());
   1782                     int dispatchStatus = mNfcDispatcher.dispatchTag(tag);
   1783                     if (dispatchStatus == NfcDispatcher.DISPATCH_SUCCESS) {
   1784                         playSound(SOUND_END);
   1785                     } else if (dispatchStatus == NfcDispatcher.DISPATCH_FAIL) {
   1786                         playSound(SOUND_ERROR);
   1787                     }
   1788                     break;
   1789                 }
   1790 
   1791                 case MSG_NDEF_TAG:
   1792                     if (DBG) Log.d(TAG, "Tag detected, notifying applications");
   1793                     TagEndpoint tag = (TagEndpoint) msg.obj;
   1794                     byte[] debounceTagUid;
   1795                     int debounceTagMs;
   1796                     ITagRemovedCallback debounceTagRemovedCallback;
   1797                     synchronized (NfcService.this) {
   1798                         debounceTagUid = mDebounceTagUid;
   1799                         debounceTagMs = mDebounceTagDebounceMs;
   1800                         debounceTagRemovedCallback = mDebounceTagRemovedCallback;
   1801                     }
   1802                     if (debounceTagUid != null) {
   1803                         if (Arrays.equals(debounceTagUid, tag.getUid())) {
   1804                              // Still ignoring this tag...poll again and reset debounce timer
   1805                             mHandler.removeMessages(MSG_TAG_DEBOUNCE);
   1806                             mHandler.sendEmptyMessageDelayed(MSG_TAG_DEBOUNCE, debounceTagMs);
   1807                             tag.disconnect();
   1808                             return;
   1809                         } else {
   1810                             synchronized (NfcService.this) {
   1811                                 mDebounceTagUid = null;
   1812                             }
   1813                             if (debounceTagRemovedCallback != null) {
   1814                                 try {
   1815                                     debounceTagRemovedCallback.onTagRemoved();
   1816                                 } catch (RemoteException e) {
   1817                                     // Ignore
   1818                                 }
   1819                             }
   1820                         }
   1821                     }
   1822                     ReaderModeParams readerParams = null;
   1823                     int presenceCheckDelay = DEFAULT_PRESENCE_CHECK_DELAY;
   1824                     DeviceHost.TagDisconnectedCallback callback =
   1825                             new DeviceHost.TagDisconnectedCallback() {
   1826                                 @Override
   1827                                 public void onTagDisconnected(long handle) {
   1828                                     applyRouting(false);
   1829                                 }
   1830                             };
   1831                     synchronized (NfcService.this) {
   1832                         readerParams = mReaderModeParams;
   1833                     }
   1834                     if (readerParams != null) {
   1835                         presenceCheckDelay = readerParams.presenceCheckDelay;
   1836                         if ((readerParams.flags & NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK) != 0) {
   1837                             if (DBG) Log.d(TAG, "Skipping NDEF detection in reader mode");
   1838                             tag.startPresenceChecking(presenceCheckDelay, callback);
   1839                             dispatchTagEndpoint(tag, readerParams);
   1840                             break;
   1841                         }
   1842                     }
   1843 
   1844                     boolean playSound = readerParams == null ||
   1845                         (readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0;
   1846                     if (mScreenState == ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED && playSound) {
   1847                         playSound(SOUND_START);
   1848                     }
   1849                     if (tag.getConnectedTechnology() == TagTechnology.NFC_BARCODE) {
   1850                         // When these tags start containing NDEF, they will require
   1851                         // the stack to deal with them in a different way, since
   1852                         // they are activated only really shortly.
   1853                         // For now, don't consider NDEF on these.
   1854                         if (DBG) Log.d(TAG, "Skipping NDEF detection for NFC Barcode");
   1855                         tag.startPresenceChecking(presenceCheckDelay, callback);
   1856                         dispatchTagEndpoint(tag, readerParams);
   1857                         break;
   1858                     }
   1859                     NdefMessage ndefMsg = tag.findAndReadNdef();
   1860 
   1861                     if (ndefMsg != null) {
   1862                         tag.startPresenceChecking(presenceCheckDelay, callback);
   1863                         dispatchTagEndpoint(tag, readerParams);
   1864                     } else {
   1865                         if (tag.reconnect()) {
   1866                             tag.startPresenceChecking(presenceCheckDelay, callback);
   1867                             dispatchTagEndpoint(tag, readerParams);
   1868                         } else {
   1869                             tag.disconnect();
   1870                             playSound(SOUND_ERROR);
   1871                         }
   1872                     }
   1873                     break;
   1874                 case MSG_LLCP_LINK_ACTIVATION:
   1875                     if (mIsDebugBuild) {
   1876                         Intent actIntent = new Intent(ACTION_LLCP_UP);
   1877                         mContext.sendBroadcast(actIntent);
   1878                     }
   1879                     llcpActivated((NfcDepEndpoint) msg.obj);
   1880                     break;
   1881 
   1882                 case MSG_LLCP_LINK_DEACTIVATED:
   1883                     if (mIsDebugBuild) {
   1884                         Intent deactIntent = new Intent(ACTION_LLCP_DOWN);
   1885                         mContext.sendBroadcast(deactIntent);
   1886                     }
   1887                     NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
   1888                     boolean needsDisconnect = false;
   1889 
   1890                     Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
   1891                     synchronized (NfcService.this) {
   1892                         /* Check if the device has been already unregistered */
   1893                         if (mObjectMap.remove(device.getHandle()) != null) {
   1894                             /* Disconnect if we are initiator */
   1895                             if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
   1896                                 if (DBG) Log.d(TAG, "disconnecting from target");
   1897                                 needsDisconnect = true;
   1898                             } else {
   1899                                 if (DBG) Log.d(TAG, "not disconnecting from initiator");
   1900                             }
   1901                         }
   1902                     }
   1903                     if (needsDisconnect) {
   1904                         device.disconnect();  // restarts polling loop
   1905                     }
   1906 
   1907                     mP2pLinkManager.onLlcpDeactivated();
   1908                     break;
   1909                 case MSG_LLCP_LINK_FIRST_PACKET:
   1910                     mP2pLinkManager.onLlcpFirstPacketReceived();
   1911                     break;
   1912                 case MSG_RF_FIELD_ACTIVATED:
   1913                     Intent fieldOnIntent = new Intent(ACTION_RF_FIELD_ON_DETECTED);
   1914                     sendNfcEeAccessProtectedBroadcast(fieldOnIntent);
   1915                     break;
   1916                 case MSG_RF_FIELD_DEACTIVATED:
   1917                     Intent fieldOffIntent = new Intent(ACTION_RF_FIELD_OFF_DETECTED);
   1918                     sendNfcEeAccessProtectedBroadcast(fieldOffIntent);
   1919                     break;
   1920                 case MSG_RESUME_POLLING:
   1921                     mNfcAdapter.resumePolling();
   1922                     break;
   1923                 case MSG_TAG_DEBOUNCE:
   1924                     // Didn't see the tag again, tag is gone
   1925                     ITagRemovedCallback tagRemovedCallback;
   1926                     synchronized (NfcService.this) {
   1927                         mDebounceTagUid = null;
   1928                         tagRemovedCallback = mDebounceTagRemovedCallback;
   1929                     }
   1930                     if (tagRemovedCallback != null) {
   1931                         try {
   1932                             tagRemovedCallback.onTagRemoved();
   1933                         } catch (RemoteException e) {
   1934                             // Ignore
   1935                         }
   1936                     }
   1937                     break;
   1938                 default:
   1939                     Log.e(TAG, "Unknown message received");
   1940                     break;
   1941             }
   1942         }
   1943 
   1944         private void sendNfcEeAccessProtectedBroadcast(Intent intent) {
   1945             intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
   1946             // Resume app switches so the receivers can start activites without delay
   1947             mNfcDispatcher.resumeAppSwitches();
   1948             ArrayList<String> matchingPackages = new ArrayList<String>();
   1949             ArrayList<String> preferredPackages = new ArrayList<String>();
   1950             synchronized (this) {
   1951                 for (PackageInfo pkg : mInstalledPackages) {
   1952                     if (pkg != null && pkg.applicationInfo != null) {
   1953                         if (mNfceeAccessControl.check(pkg.applicationInfo)) {
   1954                             matchingPackages.add(pkg.packageName);
   1955                             if (mCardEmulationManager != null &&
   1956                                     mCardEmulationManager.packageHasPreferredService(pkg.packageName)) {
   1957                                 preferredPackages.add(pkg.packageName);
   1958                             }
   1959                         }
   1960                     }
   1961                 }
   1962                 if (preferredPackages.size() > 0) {
   1963                     // If there's any packages in here which are preferred, only
   1964                     // send field events to those packages, to prevent other apps
   1965                     // with signatures in nfcee_access.xml from acting upon the events.
   1966                     for (String packageName : preferredPackages){
   1967                         intent.setPackage(packageName);
   1968                         mContext.sendBroadcast(intent);
   1969                     }
   1970                 } else {
   1971                     for (String packageName : matchingPackages){
   1972                         intent.setPackage(packageName);
   1973                         mContext.sendBroadcast(intent);
   1974                     }
   1975                 }
   1976             }
   1977         }
   1978 
   1979         private boolean llcpActivated(NfcDepEndpoint device) {
   1980             Log.d(TAG, "LLCP Activation message");
   1981 
   1982             if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
   1983                 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
   1984                 if (device.connect()) {
   1985                     /* Check LLCP compliancy */
   1986                     if (mDeviceHost.doCheckLlcp()) {
   1987                         /* Activate LLCP Link */
   1988                         if (mDeviceHost.doActivateLlcp()) {
   1989                             if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
   1990                             synchronized (NfcService.this) {
   1991                                 // Register P2P device
   1992                                 mObjectMap.put(device.getHandle(), device);
   1993                             }
   1994                             mP2pLinkManager.onLlcpActivated(device.getLlcpVersion());
   1995                             return true;
   1996                         } else {
   1997                             /* should not happen */
   1998                             Log.w(TAG, "Initiator LLCP activation failed. Disconnect.");
   1999                             device.disconnect();
   2000                         }
   2001                     } else {
   2002                         if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
   2003                         device.disconnect();
   2004                     }
   2005                 } else {
   2006                     if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted.");
   2007                     /*
   2008                      * The polling loop should have been restarted in failing
   2009                      * doConnect
   2010                      */
   2011                 }
   2012             } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
   2013                 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
   2014                 /* Check LLCP compliancy */
   2015                 if (mDeviceHost.doCheckLlcp()) {
   2016                     /* Activate LLCP Link */
   2017                     if (mDeviceHost.doActivateLlcp()) {
   2018                         if (DBG) Log.d(TAG, "Target Activate LLCP OK");
   2019                         synchronized (NfcService.this) {
   2020                             // Register P2P device
   2021                             mObjectMap.put(device.getHandle(), device);
   2022                         }
   2023                         mP2pLinkManager.onLlcpActivated(device.getLlcpVersion());
   2024                         return true;
   2025                     }
   2026                 } else {
   2027                     Log.w(TAG, "checkLlcp failed");
   2028                 }
   2029             }
   2030 
   2031             return false;
   2032         }
   2033 
   2034         private void dispatchTagEndpoint(TagEndpoint tagEndpoint, ReaderModeParams readerParams) {
   2035             Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
   2036                     tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
   2037             registerTagObject(tagEndpoint);
   2038             if (readerParams != null) {
   2039                 try {
   2040                     if ((readerParams.flags & NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS) == 0) {
   2041                         playSound(SOUND_END);
   2042                     }
   2043                     if (readerParams.callback != null) {
   2044                         readerParams.callback.onTagDiscovered(tag);
   2045                         return;
   2046                     } else {
   2047                         // Follow normal dispatch below
   2048                     }
   2049                 } catch (RemoteException e) {
   2050                     Log.e(TAG, "Reader mode remote has died, falling back.", e);
   2051                     // Intentional fall-through
   2052                 } catch (Exception e) {
   2053                     // Catch any other exception
   2054                     Log.e(TAG, "App exception, not dispatching.", e);
   2055                     return;
   2056                 }
   2057             }
   2058             int dispatchResult = mNfcDispatcher.dispatchTag(tag);
   2059             if (dispatchResult == NfcDispatcher.DISPATCH_FAIL) {
   2060                 unregisterObject(tagEndpoint.getHandle());
   2061                 playSound(SOUND_ERROR);
   2062             } else if (dispatchResult == NfcDispatcher.DISPATCH_SUCCESS) {
   2063                 playSound(SOUND_END);
   2064             }
   2065         }
   2066     }
   2067 
   2068     private NfcServiceHandler mHandler = new NfcServiceHandler();
   2069 
   2070     class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> {
   2071         @Override
   2072         protected Void doInBackground(Integer... params) {
   2073             synchronized (NfcService.this) {
   2074                 if (params == null || params.length != 1) {
   2075                     // force apply current routing
   2076                     applyRouting(true);
   2077                     return null;
   2078                 }
   2079                 mScreenState = params[0].intValue();
   2080 
   2081                 mRoutingWakeLock.acquire();
   2082                 try {
   2083                     applyRouting(false);
   2084                 } finally {
   2085                     mRoutingWakeLock.release();
   2086                 }
   2087                 return null;
   2088             }
   2089         }
   2090     }
   2091 
   2092     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
   2093         @Override
   2094         public void onReceive(Context context, Intent intent) {
   2095             String action = intent.getAction();
   2096             if (action.equals(Intent.ACTION_SCREEN_ON)
   2097                     || action.equals(Intent.ACTION_SCREEN_OFF)
   2098                     || action.equals(Intent.ACTION_USER_PRESENT)) {
   2099                 // Perform applyRouting() in AsyncTask to serialize blocking calls
   2100                 int screenState = ScreenStateHelper.SCREEN_STATE_OFF;
   2101                 if (action.equals(Intent.ACTION_SCREEN_OFF)) {
   2102                     screenState = ScreenStateHelper.SCREEN_STATE_OFF;
   2103                 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
   2104                     screenState = mKeyguard.isKeyguardLocked()
   2105                             ? ScreenStateHelper.SCREEN_STATE_ON_LOCKED
   2106                             : ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
   2107                 } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
   2108                     screenState = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
   2109                 }
   2110 
   2111                 new ApplyRoutingTask().execute(Integer.valueOf(screenState));
   2112             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
   2113                 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
   2114                 synchronized (this) {
   2115                     mUserId = userId;
   2116                 }
   2117                 mP2pLinkManager.onUserSwitched(getUserId());
   2118                 if (mIsHceCapable) {
   2119                     mCardEmulationManager.onUserSwitched(getUserId());
   2120                 }
   2121             }
   2122         }
   2123     };
   2124 
   2125 
   2126     private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
   2127         @Override
   2128         public void onReceive(Context context, Intent intent) {
   2129             String action = intent.getAction();
   2130             if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
   2131                     action.equals(Intent.ACTION_PACKAGE_ADDED) ||
   2132                     action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
   2133                     action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
   2134                 updatePackageCache();
   2135 
   2136                 if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
   2137                     // Clear the NFCEE access cache in case a UID gets recycled
   2138                     mNfceeAccessControl.invalidateCache();
   2139                 }
   2140             }
   2141         }
   2142     };
   2143 
   2144     private final BroadcastReceiver mPolicyReceiver = new BroadcastReceiver() {
   2145         @Override
   2146         public void onReceive(Context context, Intent intent){
   2147             String action = intent.getAction();
   2148             if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
   2149                     .equals(action)) {
   2150                 enforceBeamShareActivityPolicy(context,
   2151                         new UserHandle(getSendingUserId()), mIsNdefPushEnabled);
   2152             }
   2153         }
   2154     };
   2155 
   2156     /**
   2157      * for debugging only - no i18n
   2158      */
   2159     static String stateToString(int state) {
   2160         switch (state) {
   2161             case NfcAdapter.STATE_OFF:
   2162                 return "off";
   2163             case NfcAdapter.STATE_TURNING_ON:
   2164                 return "turning on";
   2165             case NfcAdapter.STATE_ON:
   2166                 return "on";
   2167             case NfcAdapter.STATE_TURNING_OFF:
   2168                 return "turning off";
   2169             default:
   2170                 return "<error>";
   2171         }
   2172     }
   2173 
   2174     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   2175         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
   2176                 != PackageManager.PERMISSION_GRANTED) {
   2177             pw.println("Permission Denial: can't dump nfc from from pid="
   2178                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
   2179                     + " without permission " + android.Manifest.permission.DUMP);
   2180             return;
   2181         }
   2182 
   2183         synchronized (this) {
   2184             pw.println("mState=" + stateToString(mState));
   2185             pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled);
   2186             pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState));
   2187             pw.println(mCurrentDiscoveryParameters);
   2188             mP2pLinkManager.dump(fd, pw, args);
   2189             if (mIsHceCapable) {
   2190                 mCardEmulationManager.dump(fd, pw, args);
   2191             }
   2192             mNfcDispatcher.dump(fd, pw, args);
   2193             pw.println(mDeviceHost.dump());
   2194         }
   2195     }
   2196 }
   2197