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