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