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