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