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