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