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