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