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