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