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