• 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 com.android.nfc.DeviceHost.DeviceHostListener;
20 import com.android.nfc.DeviceHost.LlcpConnectionlessSocket;
21 import com.android.nfc.DeviceHost.LlcpServerSocket;
22 import com.android.nfc.DeviceHost.LlcpSocket;
23 import com.android.nfc.DeviceHost.NfcDepEndpoint;
24 import com.android.nfc.DeviceHost.TagEndpoint;
25 import com.android.nfc.handover.HandoverManager;
26 import com.android.nfc.dhimpl.NativeNfcManager;
27 import com.android.nfc.dhimpl.NativeNfcSecureElement;
28 
29 import android.app.Application;
30 import android.app.KeyguardManager;
31 import android.app.PendingIntent;
32 import android.content.BroadcastReceiver;
33 import android.content.ContentResolver;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.content.SharedPreferences;
38 import android.content.pm.PackageInfo;
39 import android.content.pm.PackageManager;
40 import android.media.AudioManager;
41 import android.media.SoundPool;
42 import android.net.Uri;
43 import android.nfc.ErrorCodes;
44 import android.nfc.FormatException;
45 import android.nfc.INdefPushCallback;
46 import android.nfc.INfcAdapter;
47 import android.nfc.INfcAdapterExtras;
48 import android.nfc.INfcTag;
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.Bundle;
59 import android.os.Handler;
60 import android.os.IBinder;
61 import android.os.Message;
62 import android.os.PowerManager;
63 import android.os.Process;
64 import android.os.RemoteException;
65 import android.os.ServiceManager;
66 import android.os.UserHandle;
67 import android.provider.Settings;
68 import android.util.Log;
69 
70 import java.io.FileDescriptor;
71 import java.io.IOException;
72 import java.io.PrintWriter;
73 import java.util.Arrays;
74 import java.util.HashMap;
75 import java.util.HashSet;
76 import java.util.List;
77 import java.util.concurrent.ExecutionException;
78 
79 public class NfcService implements DeviceHostListener {
80     private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
81 
82     static final boolean DBG = false;
83     static final String TAG = "NfcService";
84 
85     public static final String SERVICE_NAME = "nfc";
86 
87     /** Regular NFC permission */
88     private static final String NFC_PERM = android.Manifest.permission.NFC;
89     private static final String NFC_PERM_ERROR = "NFC permission required";
90 
91     /** NFC ADMIN permission - only for system apps */
92     private static final String ADMIN_PERM = android.Manifest.permission.WRITE_SECURE_SETTINGS;
93     private static final String ADMIN_PERM_ERROR = "WRITE_SECURE_SETTINGS permission required";
94 
95     public static final String PREF = "NfcServicePrefs";
96 
97     static final String PREF_NFC_ON = "nfc_on";
98     static final boolean NFC_ON_DEFAULT = true;
99     static final String PREF_NDEF_PUSH_ON = "ndef_push_on";
100     static final boolean NDEF_PUSH_ON_DEFAULT = true;
101     static final String PREF_FIRST_BEAM = "first_beam";
102     static final String PREF_FIRST_BOOT = "first_boot";
103     static final String PREF_AIRPLANE_OVERRIDE = "airplane_override";
104 
105     static final int MSG_NDEF_TAG = 0;
106     static final int MSG_CARD_EMULATION = 1;
107     static final int MSG_LLCP_LINK_ACTIVATION = 2;
108     static final int MSG_LLCP_LINK_DEACTIVATED = 3;
109     static final int MSG_TARGET_DESELECTED = 4;
110     static final int MSG_MOCK_NDEF = 7;
111     static final int MSG_SE_FIELD_ACTIVATED = 8;
112     static final int MSG_SE_FIELD_DEACTIVATED = 9;
113     static final int MSG_SE_APDU_RECEIVED = 10;
114     static final int MSG_SE_EMV_CARD_REMOVAL = 11;
115     static final int MSG_SE_MIFARE_ACCESS = 12;
116     static final int MSG_SE_LISTEN_ACTIVATED = 13;
117     static final int MSG_SE_LISTEN_DEACTIVATED = 14;
118 
119     static final int TASK_ENABLE = 1;
120     static final int TASK_DISABLE = 2;
121     static final int TASK_BOOT = 3;
122     static final int TASK_EE_WIPE = 4;
123 
124     // Screen state, used by mScreenState
125     static final int SCREEN_STATE_UNKNOWN = 0;
126     static final int SCREEN_STATE_OFF = 1;
127     static final int SCREEN_STATE_ON_LOCKED = 2;
128     static final int SCREEN_STATE_ON_UNLOCKED = 3;
129 
130     // Copied from com.android.nfc_extras to avoid library dependency
131     // Must keep in sync with com.android.nfc_extras
132     static final int ROUTE_OFF = 1;
133     static final int ROUTE_ON_WHEN_SCREEN_ON = 2;
134 
135     /** minimum screen state that enables NFC polling (discovery) */
136     static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED;
137 
138     // Time to wait for NFC controller to initialize before watchdog
139     // goes off. This time is chosen large, because firmware download
140     // may be a part of initialization.
141     static final int INIT_WATCHDOG_MS = 90000;
142 
143     // Time to wait for routing to be applied before watchdog
144     // goes off
145     static final int ROUTING_WATCHDOG_MS = 10000;
146 
147     // for use with playSound()
148     public static final int SOUND_START = 0;
149     public static final int SOUND_END = 1;
150     public static final int SOUND_ERROR = 2;
151 
152     public static final String ACTION_RF_FIELD_ON_DETECTED =
153         "com.android.nfc_extras.action.RF_FIELD_ON_DETECTED";
154     public static final String ACTION_RF_FIELD_OFF_DETECTED =
155         "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
156     public static final String ACTION_AID_SELECTED =
157         "com.android.nfc_extras.action.AID_SELECTED";
158     public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
159 
160     public static final String ACTION_APDU_RECEIVED =
161         "com.android.nfc_extras.action.APDU_RECEIVED";
162     public static final String EXTRA_APDU_BYTES =
163         "com.android.nfc_extras.extra.APDU_BYTES";
164 
165     public static final String ACTION_EMV_CARD_REMOVAL =
166         "com.android.nfc_extras.action.EMV_CARD_REMOVAL";
167 
168     public static final String ACTION_MIFARE_ACCESS_DETECTED =
169         "com.android.nfc_extras.action.MIFARE_ACCESS_DETECTED";
170     public static final String EXTRA_MIFARE_BLOCK =
171         "com.android.nfc_extras.extra.MIFARE_BLOCK";
172 
173     public static final String ACTION_SE_LISTEN_ACTIVATED =
174             "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED";
175     public static final String ACTION_SE_LISTEN_DEACTIVATED =
176             "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED";
177 
178     // NFC Execution Environment
179     // fields below are protected by this
180     private NativeNfcSecureElement mSecureElement;
181     private OpenSecureElement mOpenEe;  // null when EE closed
182     private int mEeRoutingState;  // contactless interface routing
183 
184     // fields below must be used only on the UI thread and therefore aren't synchronized
185     boolean mP2pStarted = false;
186 
187     // fields below are used in multiple threads and protected by synchronized(this)
188     final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
189     // mSePackages holds packages that accessed the SE, but only for the owner user,
190     // as SE access is not granted for non-owner users.
191     HashSet<String> mSePackages = new HashSet<String>();
192     int mScreenState;
193     boolean mIsNdefPushEnabled;
194     boolean mNfceeRouteEnabled;  // current Device Host state of NFC-EE routing
195     boolean mNfcPollingEnabled;  // current Device Host state of NFC-C polling
196     List<PackageInfo> mInstalledPackages; // cached version of installed packages
197 
198     // mState is protected by this, however it is only modified in onCreate()
199     // and the default AsyncTask thread so it is read unprotected from that
200     // thread
201     int mState;  // one of NfcAdapter.STATE_ON, STATE_TURNING_ON, etc
202 
203     // fields below are final after onCreate()
204     Context mContext;
205     private DeviceHost mDeviceHost;
206     private SharedPreferences mPrefs;
207     private SharedPreferences.Editor mPrefsEditor;
208     private PowerManager.WakeLock mRoutingWakeLock;
209     private PowerManager.WakeLock mEeWakeLock;
210 
211     int mStartSound;
212     int mEndSound;
213     int mErrorSound;
214     SoundPool mSoundPool; // playback synchronized on this
215     P2pLinkManager mP2pLinkManager;
216     TagService mNfcTagService;
217     NfcAdapterService mNfcAdapter;
218     NfcAdapterExtrasService mExtrasService;
219     boolean mIsAirplaneSensitive;
220     boolean mIsAirplaneToggleable;
221     NfceeAccessControl mNfceeAccessControl;
222 
223     private NfcDispatcher mNfcDispatcher;
224     private PowerManager mPowerManager;
225     private KeyguardManager mKeyguard;
226 
227     private static NfcService sService;
228 
enforceAdminPerm(Context context)229     public static void enforceAdminPerm(Context context) {
230         context.enforceCallingOrSelfPermission(ADMIN_PERM, ADMIN_PERM_ERROR);
231     }
232 
enforceNfceeAdminPerm(String pkg)233     public void enforceNfceeAdminPerm(String pkg) {
234         if (pkg == null) {
235             throw new SecurityException("caller must pass a package name");
236         }
237         mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
238         if (!mNfceeAccessControl.check(Binder.getCallingUid(), pkg)) {
239             throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
240                     " denies NFCEE access to " + pkg);
241         }
242         if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
243             throw new SecurityException("only the owner is allowed to call SE APIs");
244         }
245     }
246 
getInstance()247     public static NfcService getInstance() {
248         return sService;
249     }
250 
251     @Override
onRemoteEndpointDiscovered(TagEndpoint tag)252     public void onRemoteEndpointDiscovered(TagEndpoint tag) {
253         sendMessage(NfcService.MSG_NDEF_TAG, tag);
254     }
255 
256     /**
257      * Notifies transaction
258      */
259     @Override
onCardEmulationDeselected()260     public void onCardEmulationDeselected() {
261         sendMessage(NfcService.MSG_TARGET_DESELECTED, null);
262     }
263 
264     /**
265      * Notifies transaction
266      */
267     @Override
onCardEmulationAidSelected(byte[] aid)268     public void onCardEmulationAidSelected(byte[] aid) {
269         sendMessage(NfcService.MSG_CARD_EMULATION, aid);
270     }
271 
272     /**
273      * Notifies P2P Device detected, to activate LLCP link
274      */
275     @Override
onLlcpLinkActivated(NfcDepEndpoint device)276     public void onLlcpLinkActivated(NfcDepEndpoint device) {
277         sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
278     }
279 
280     /**
281      * Notifies P2P Device detected, to activate LLCP link
282      */
283     @Override
onLlcpLinkDeactivated(NfcDepEndpoint device)284     public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
285         sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
286     }
287 
288     @Override
onRemoteFieldActivated()289     public void onRemoteFieldActivated() {
290         sendMessage(NfcService.MSG_SE_FIELD_ACTIVATED, null);
291     }
292 
293     @Override
onRemoteFieldDeactivated()294     public void onRemoteFieldDeactivated() {
295         sendMessage(NfcService.MSG_SE_FIELD_DEACTIVATED, null);
296     }
297 
298     @Override
onSeListenActivated()299     public void onSeListenActivated() {
300         sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null);
301     }
302 
303     @Override
onSeListenDeactivated()304     public void onSeListenDeactivated() {
305         sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null);
306     }
307 
308 
309     @Override
onSeApduReceived(byte[] apdu)310     public void onSeApduReceived(byte[] apdu) {
311         sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu);
312     }
313 
314     @Override
onSeEmvCardRemoval()315     public void onSeEmvCardRemoval() {
316         sendMessage(NfcService.MSG_SE_EMV_CARD_REMOVAL, null);
317     }
318 
319     @Override
onSeMifareAccess(byte[] block)320     public void onSeMifareAccess(byte[] block) {
321         sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block);
322     }
323 
NfcService(Application nfcApplication)324     public NfcService(Application nfcApplication) {
325         mNfcTagService = new TagService();
326         mNfcAdapter = new NfcAdapterService();
327         mExtrasService = new NfcAdapterExtrasService();
328 
329         Log.i(TAG, "Starting NFC service");
330 
331         sService = this;
332 
333         mContext = nfcApplication;
334         mDeviceHost = new NativeNfcManager(mContext, this);
335 
336         HandoverManager handoverManager = new HandoverManager(mContext);
337         mNfcDispatcher = new NfcDispatcher(mContext, handoverManager);
338 
339         mP2pLinkManager = new P2pLinkManager(mContext, handoverManager,
340                 mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
341 
342         mSecureElement = new NativeNfcSecureElement(mContext);
343         mEeRoutingState = ROUTE_OFF;
344 
345         mNfceeAccessControl = new NfceeAccessControl(mContext);
346 
347         mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
348         mPrefsEditor = mPrefs.edit();
349 
350         mState = NfcAdapter.STATE_OFF;
351         mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
352 
353         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
354 
355         mRoutingWakeLock = mPowerManager.newWakeLock(
356             PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
357         mEeWakeLock = mPowerManager.newWakeLock(
358             PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock");
359 
360         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
361         mScreenState = checkScreenState();
362 
363         ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
364 
365         // Intents only for owner
366         IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
367         ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
368         ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
369         ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
370 
371         mContext.registerReceiver(mOwnerReceiver, ownerFilter);
372 
373         ownerFilter = new IntentFilter();
374         ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
375         ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
376         ownerFilter.addDataScheme("package");
377 
378         mContext.registerReceiver(mOwnerReceiver, ownerFilter);
379 
380         // Intents for all users
381         IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
382         filter.addAction(Intent.ACTION_SCREEN_OFF);
383         filter.addAction(Intent.ACTION_SCREEN_ON);
384         filter.addAction(Intent.ACTION_USER_PRESENT);
385         registerForAirplaneMode(filter);
386         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
387 
388         updatePackageCache();
389 
390         new EnableDisableTask().execute(TASK_BOOT);  // do blocking boot tasks
391     }
392 
initSoundPool()393     void initSoundPool() {
394         synchronized(this) {
395             if (mSoundPool == null) {
396                 mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
397                 mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
398                 mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
399                 mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
400             }
401         }
402     }
403 
releaseSoundPool()404     void releaseSoundPool() {
405         synchronized(this) {
406             if (mSoundPool != null) {
407                 mSoundPool.release();
408                 mSoundPool = null;
409             }
410         }
411     }
412 
registerForAirplaneMode(IntentFilter filter)413     void registerForAirplaneMode(IntentFilter filter) {
414         final ContentResolver resolver = mContext.getContentResolver();
415         final String airplaneModeRadios = Settings.System.getString(resolver,
416                 Settings.System.AIRPLANE_MODE_RADIOS);
417         final String toggleableRadios = Settings.System.getString(resolver,
418                 Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
419 
420         mIsAirplaneSensitive = airplaneModeRadios == null ? true :
421                 airplaneModeRadios.contains(Settings.System.RADIO_NFC);
422         mIsAirplaneToggleable = toggleableRadios == null ? false :
423             toggleableRadios.contains(Settings.System.RADIO_NFC);
424 
425         if (mIsAirplaneSensitive) {
426             filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
427         }
428     }
429 
updatePackageCache()430     void updatePackageCache() {
431         PackageManager pm = mContext.getPackageManager();
432         List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER);
433         synchronized (this) {
434             mInstalledPackages = packages;
435         }
436     }
437 
checkScreenState()438     int checkScreenState() {
439         if (!mPowerManager.isScreenOn()) {
440             return SCREEN_STATE_OFF;
441         } else if (mKeyguard.isKeyguardLocked()) {
442             return SCREEN_STATE_ON_LOCKED;
443         } else {
444             return SCREEN_STATE_ON_UNLOCKED;
445         }
446     }
447 
doOpenSecureElementConnection()448     int doOpenSecureElementConnection() {
449         mEeWakeLock.acquire();
450         try {
451             return mSecureElement.doOpenSecureElementConnection();
452         } finally {
453             mEeWakeLock.release();
454         }
455     }
456 
doTransceive(int handle, byte[] cmd)457     byte[] doTransceive(int handle, byte[] cmd) {
458         mEeWakeLock.acquire();
459         try {
460             return doTransceiveNoLock(handle, cmd);
461         } finally {
462             mEeWakeLock.release();
463         }
464     }
465 
doTransceiveNoLock(int handle, byte[] cmd)466     byte[] doTransceiveNoLock(int handle, byte[] cmd) {
467         return mSecureElement.doTransceive(handle, cmd);
468     }
469 
doDisconnect(int handle)470     void doDisconnect(int handle) {
471         mEeWakeLock.acquire();
472         try {
473             mSecureElement.doDisconnect(handle);
474         } finally {
475             mEeWakeLock.release();
476         }
477     }
478 
479     /**
480      * Manages tasks that involve turning on/off the NFC controller.
481      *
482      * <p>All work that might turn the NFC adapter on or off must be done
483      * through this task, to keep the handling of mState simple.
484      * In other words, mState is only modified in these tasks (and we
485      * don't need a lock to read it in these tasks).
486      *
487      * <p>These tasks are all done on the same AsyncTask background
488      * thread, so they are serialized. Each task may temporarily transition
489      * mState to STATE_TURNING_OFF or STATE_TURNING_ON, but must exit in
490      * either STATE_ON or STATE_OFF. This way each task can be guaranteed
491      * of starting in either STATE_OFF or STATE_ON, without needing to hold
492      * NfcService.this for the entire task.
493      *
494      * <p>AsyncTask's are also implicitly queued. This is useful for corner
495      * cases like turning airplane mode on while TASK_ENABLE is in progress.
496      * The TASK_DISABLE triggered by airplane mode will be correctly executed
497      * immediately after TASK_ENABLE is complete. This seems like the most sane
498      * way to deal with these situations.
499      *
500      * <p>{@link #TASK_ENABLE} enables the NFC adapter, without changing
501      * preferences
502      * <p>{@link #TASK_DISABLE} disables the NFC adapter, without changing
503      * preferences
504      * <p>{@link #TASK_BOOT} does first boot work and may enable NFC
505      * <p>{@link #TASK_EE_WIPE} wipes the Execution Environment, and in the
506      * process may temporarily enable the NFC adapter
507      */
508     class EnableDisableTask extends AsyncTask<Integer, Void, Void> {
509         @Override
doInBackground(Integer... params)510         protected Void doInBackground(Integer... params) {
511             // Sanity check mState
512             switch (mState) {
513                 case NfcAdapter.STATE_TURNING_OFF:
514                 case NfcAdapter.STATE_TURNING_ON:
515                     Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " +
516                             mState);
517                     return null;
518             }
519 
520             /* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND,
521              * override with the default. THREAD_PRIORITY_BACKGROUND causes
522              * us to service software I2C too slow for firmware download
523              * with the NXP PN544.
524              * TODO: move this to the DAL I2C layer in libnfc-nxp, since this
525              * problem only occurs on I2C platforms using PN544
526              */
527             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
528 
529             switch (params[0].intValue()) {
530                 case TASK_ENABLE:
531                     enableInternal();
532                     break;
533                 case TASK_DISABLE:
534                     disableInternal();
535                     break;
536                 case TASK_BOOT:
537                     Log.d(TAG,"checking on firmware download");
538                     boolean airplaneOverride = mPrefs.getBoolean(PREF_AIRPLANE_OVERRIDE, false);
539                     if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT) &&
540                             (!mIsAirplaneSensitive || !isAirplaneModeOn() || airplaneOverride)) {
541                         Log.d(TAG,"NFC is on. Doing normal stuff");
542                         enableInternal();
543                     } else {
544                         Log.d(TAG,"NFC is off.  Checking firmware version");
545                         mDeviceHost.checkFirmware();
546                     }
547                     if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
548                         Log.i(TAG, "First Boot");
549                         mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
550                         mPrefsEditor.apply();
551                         executeEeWipe();
552                     }
553                     break;
554                 case TASK_EE_WIPE:
555                     executeEeWipe();
556                     break;
557             }
558 
559             // Restore default AsyncTask priority
560             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
561             return null;
562         }
563 
564         /**
565          * Enable NFC adapter functions.
566          * Does not toggle preferences.
567          */
enableInternal()568         boolean enableInternal() {
569             if (mState == NfcAdapter.STATE_ON) {
570                 return true;
571             }
572             Log.i(TAG, "Enabling NFC");
573             updateState(NfcAdapter.STATE_TURNING_ON);
574 
575             WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS);
576             watchDog.start();
577             try {
578                 mRoutingWakeLock.acquire();
579                 try {
580                     if (!mDeviceHost.initialize()) {
581                         Log.w(TAG, "Error enabling NFC");
582                         updateState(NfcAdapter.STATE_OFF);
583                         return false;
584                     }
585                 } finally {
586                     mRoutingWakeLock.release();
587                 }
588             } finally {
589                 watchDog.cancel();
590             }
591 
592             synchronized(NfcService.this) {
593                 mObjectMap.clear();
594 
595                 mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
596                 updateState(NfcAdapter.STATE_ON);
597             }
598 
599             initSoundPool();
600 
601             /* Start polling loop */
602 
603             applyRouting(true);
604             return true;
605         }
606 
607         /**
608          * Disable all NFC adapter functions.
609          * Does not toggle preferences.
610          */
disableInternal()611         boolean disableInternal() {
612             if (mState == NfcAdapter.STATE_OFF) {
613                 return true;
614             }
615             Log.i(TAG, "Disabling NFC");
616             updateState(NfcAdapter.STATE_TURNING_OFF);
617 
618             /* Sometimes mDeviceHost.deinitialize() hangs, use a watch-dog.
619              * Implemented with a new thread (instead of a Handler or AsyncTask),
620              * because the UI Thread and AsyncTask thread-pools can also get hung
621              * when the NFC controller stops responding */
622             WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS);
623             watchDog.start();
624 
625             mP2pLinkManager.enableDisable(false, false);
626 
627             synchronized (NfcService.this) {
628                 if (mOpenEe != null) {
629                     try {
630                         _nfcEeClose(-1, mOpenEe.binder);
631                     } catch (IOException e) { }
632                 }
633             }
634 
635             // Stop watchdog if tag present
636             // A convenient way to stop the watchdog properly consists of
637             // disconnecting the tag. The polling loop shall be stopped before
638             // to avoid the tag being discovered again.
639             maybeDisconnectTarget();
640 
641             mNfcDispatcher.setForegroundDispatch(null, null, null);
642 
643             boolean result = mDeviceHost.deinitialize();
644             if (DBG) Log.d(TAG, "mDeviceHost.deinitialize() = " + result);
645 
646             watchDog.cancel();
647 
648             updateState(NfcAdapter.STATE_OFF);
649 
650             releaseSoundPool();
651 
652             return result;
653         }
654 
executeEeWipe()655         void executeEeWipe() {
656             // TODO: read SE reset list from /system/etc
657             byte[][]apdus = mDeviceHost.getWipeApdus();
658 
659             if (apdus == null) {
660                 Log.d(TAG, "No wipe APDUs found");
661                 return;
662             }
663 
664             boolean tempEnable = mState == NfcAdapter.STATE_OFF;
665             // Hold a wake-lock over the entire wipe procedure
666             mEeWakeLock.acquire();
667             try {
668                 if (tempEnable && !enableInternal()) {
669                     Log.w(TAG, "Could not enable NFC to wipe NFC-EE");
670                     return;
671                 }
672                 try {
673                     // NFC enabled
674                     int handle = 0;
675                     try {
676                         Log.i(TAG, "Executing SE wipe");
677                         handle = doOpenSecureElementConnection();
678                         if (handle == 0) {
679                             Log.w(TAG, "Could not open the secure element");
680                             return;
681                         }
682                         // TODO: remove this hack
683                         try {
684                             Thread.sleep(1000);
685                         } catch (InterruptedException e) {
686                             // Ignore
687                         }
688 
689                         mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
690                         try {
691                             for (byte[] cmd : apdus) {
692                                 byte[] resp = doTransceiveNoLock(handle, cmd);
693                                 if (resp == null) {
694                                     Log.w(TAG, "Transceive failed, could not wipe NFC-EE");
695                                     break;
696                                 }
697                             }
698                         } finally {
699                             mDeviceHost.resetTimeouts();
700                         }
701                     } finally {
702                         if (handle != 0) {
703                             doDisconnect(handle);
704                         }
705                     }
706                 } finally {
707                     if (tempEnable) {
708                         disableInternal();
709                     }
710                 }
711             } finally {
712                 mEeWakeLock.release();
713             }
714             Log.i(TAG, "SE wipe done");
715         }
716 
updateState(int newState)717         void updateState(int newState) {
718             synchronized (NfcService.this) {
719                 if (newState == mState) {
720                     return;
721                 }
722                 mState = newState;
723                 Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
724                 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
725                 intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
726                 mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
727             }
728         }
729     }
730 
saveNfcOnSetting(boolean on)731     void saveNfcOnSetting(boolean on) {
732         synchronized (NfcService.this) {
733             mPrefsEditor.putBoolean(PREF_NFC_ON, on);
734             mPrefsEditor.apply();
735         }
736     }
737 
playSound(int sound)738     public void playSound(int sound) {
739         synchronized (this) {
740             if (mSoundPool == null) {
741                 Log.w(TAG, "Not playing sound when NFC is disabled");
742                 return;
743             }
744             switch (sound) {
745                 case SOUND_START:
746                     mSoundPool.play(mStartSound, 1.0f, 1.0f, 0, 0, 1.0f);
747                     break;
748                 case SOUND_END:
749                     mSoundPool.play(mEndSound, 1.0f, 1.0f, 0, 0, 1.0f);
750                     break;
751                 case SOUND_ERROR:
752                     mSoundPool.play(mErrorSound, 1.0f, 1.0f, 0, 0, 1.0f);
753                     break;
754             }
755         }
756     }
757 
758 
759     final class NfcAdapterService extends INfcAdapter.Stub {
760         @Override
enable()761         public boolean enable() throws RemoteException {
762             NfcService.enforceAdminPerm(mContext);
763 
764             saveNfcOnSetting(true);
765 
766             if (mIsAirplaneSensitive && isAirplaneModeOn()) {
767                 if (!mIsAirplaneToggleable) {
768                     Log.i(TAG, "denying enable() request (airplane mode)");
769                     return false;
770                 }
771                 // Make sure the override survives a reboot
772                 mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, true);
773                 mPrefsEditor.apply();
774             }
775             new EnableDisableTask().execute(TASK_ENABLE);
776 
777             return true;
778         }
779 
780         @Override
disable(boolean saveState)781         public boolean disable(boolean saveState) throws RemoteException {
782             NfcService.enforceAdminPerm(mContext);
783 
784             if (saveState) {
785                 saveNfcOnSetting(false);
786             }
787 
788             new EnableDisableTask().execute(TASK_DISABLE);
789 
790             return true;
791         }
792 
793         @Override
isNdefPushEnabled()794         public boolean isNdefPushEnabled() throws RemoteException {
795             synchronized (NfcService.this) {
796                 return mState == NfcAdapter.STATE_ON && mIsNdefPushEnabled;
797             }
798         }
799 
800         @Override
enableNdefPush()801         public boolean enableNdefPush() throws RemoteException {
802             NfcService.enforceAdminPerm(mContext);
803             synchronized(NfcService.this) {
804                 if (mIsNdefPushEnabled) {
805                     return true;
806                 }
807                 Log.i(TAG, "enabling NDEF Push");
808                 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, true);
809                 mPrefsEditor.apply();
810                 mIsNdefPushEnabled = true;
811                 if (isNfcEnabled()) {
812                     mP2pLinkManager.enableDisable(true, true);
813                 }
814             }
815             return true;
816         }
817 
818         @Override
disableNdefPush()819         public boolean disableNdefPush() throws RemoteException {
820             NfcService.enforceAdminPerm(mContext);
821             synchronized(NfcService.this) {
822                 if (!mIsNdefPushEnabled) {
823                     return true;
824                 }
825                 Log.i(TAG, "disabling NDEF Push");
826                 mPrefsEditor.putBoolean(PREF_NDEF_PUSH_ON, false);
827                 mPrefsEditor.apply();
828                 mIsNdefPushEnabled = false;
829                 if (isNfcEnabled()) {
830                     mP2pLinkManager.enableDisable(false, true);
831                 }
832             }
833             return true;
834         }
835 
836         @Override
setForegroundDispatch(PendingIntent intent, IntentFilter[] filters, TechListParcel techListsParcel)837         public void setForegroundDispatch(PendingIntent intent,
838                 IntentFilter[] filters, TechListParcel techListsParcel) {
839             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
840 
841             // Short-cut the disable path
842             if (intent == null && filters == null && techListsParcel == null) {
843                 mNfcDispatcher.setForegroundDispatch(null, null, null);
844                 return;
845             }
846 
847             // Validate the IntentFilters
848             if (filters != null) {
849                 if (filters.length == 0) {
850                     filters = null;
851                 } else {
852                     for (IntentFilter filter : filters) {
853                         if (filter == null) {
854                             throw new IllegalArgumentException("null IntentFilter");
855                         }
856                     }
857                 }
858             }
859 
860             // Validate the tech lists
861             String[][] techLists = null;
862             if (techListsParcel != null) {
863                 techLists = techListsParcel.getTechLists();
864             }
865 
866             mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
867         }
868 
869         @Override
setNdefPushCallback(INdefPushCallback callback)870         public void setNdefPushCallback(INdefPushCallback callback) {
871             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
872             mP2pLinkManager.setNdefCallback(callback);
873         }
874 
875         @Override
getNfcTagInterface()876         public INfcTag getNfcTagInterface() throws RemoteException {
877             return mNfcTagService;
878         }
879 
880         @Override
getNfcAdapterExtrasInterface(String pkg)881         public INfcAdapterExtras getNfcAdapterExtrasInterface(String pkg) {
882             NfcService.this.enforceNfceeAdminPerm(pkg);
883             return mExtrasService;
884         }
885 
886         @Override
getState()887         public int getState() throws RemoteException {
888             synchronized (NfcService.this) {
889                 return mState;
890             }
891         }
892 
893         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)894         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
895             NfcService.this.dump(fd, pw, args);
896         }
897 
898         @Override
dispatch(Tag tag)899         public void dispatch(Tag tag) throws RemoteException {
900             enforceAdminPerm(mContext);
901             mNfcDispatcher.dispatchTag(tag);
902         }
903 
904         @Override
setP2pModes(int initiatorModes, int targetModes)905         public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
906             enforceAdminPerm(mContext);
907 
908             mDeviceHost.setP2pInitiatorModes(initiatorModes);
909             mDeviceHost.setP2pTargetModes(targetModes);
910             mDeviceHost.disableDiscovery();
911             mDeviceHost.enableDiscovery();
912         }
913     }
914 
915     final class TagService extends INfcTag.Stub {
916         @Override
close(int nativeHandle)917         public int close(int nativeHandle) throws RemoteException {
918             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
919 
920             TagEndpoint tag = null;
921 
922             if (!isNfcEnabled()) {
923                 return ErrorCodes.ERROR_NOT_INITIALIZED;
924             }
925 
926             /* find the tag in the hmap */
927             tag = (TagEndpoint) findObject(nativeHandle);
928             if (tag != null) {
929                 /* Remove the device from the hmap */
930                 unregisterObject(nativeHandle);
931                 tag.disconnect();
932                 return ErrorCodes.SUCCESS;
933             }
934             /* Restart polling loop for notification */
935             applyRouting(true);
936             return ErrorCodes.ERROR_DISCONNECT;
937         }
938 
939         @Override
connect(int nativeHandle, int technology)940         public int connect(int nativeHandle, int technology) throws RemoteException {
941             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
942 
943             TagEndpoint tag = null;
944 
945             if (!isNfcEnabled()) {
946                 return ErrorCodes.ERROR_NOT_INITIALIZED;
947             }
948 
949             /* find the tag in the hmap */
950             tag = (TagEndpoint) findObject(nativeHandle);
951             if (tag == null) {
952                 return ErrorCodes.ERROR_DISCONNECT;
953             }
954 
955             if (!tag.isPresent()) {
956                 return ErrorCodes.ERROR_DISCONNECT;
957             }
958 
959             // Note that on most tags, all technologies are behind a single
960             // handle. This means that the connect at the lower levels
961             // will do nothing, as the tag is already connected to that handle.
962             if (tag.connect(technology)) {
963                 return ErrorCodes.SUCCESS;
964             } else {
965                 return ErrorCodes.ERROR_DISCONNECT;
966             }
967         }
968 
969         @Override
reconnect(int nativeHandle)970         public int reconnect(int nativeHandle) throws RemoteException {
971             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
972 
973             TagEndpoint tag = null;
974 
975             // Check if NFC is enabled
976             if (!isNfcEnabled()) {
977                 return ErrorCodes.ERROR_NOT_INITIALIZED;
978             }
979 
980             /* find the tag in the hmap */
981             tag = (TagEndpoint) findObject(nativeHandle);
982             if (tag != null) {
983                 if (tag.reconnect()) {
984                     return ErrorCodes.SUCCESS;
985                 } else {
986                     return ErrorCodes.ERROR_DISCONNECT;
987                 }
988             }
989             return ErrorCodes.ERROR_DISCONNECT;
990         }
991 
992         @Override
getTechList(int nativeHandle)993         public int[] getTechList(int nativeHandle) throws RemoteException {
994             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
995 
996             // Check if NFC is enabled
997             if (!isNfcEnabled()) {
998                 return null;
999             }
1000 
1001             /* find the tag in the hmap */
1002             TagEndpoint tag = (TagEndpoint) findObject(nativeHandle);
1003             if (tag != null) {
1004                 return tag.getTechList();
1005             }
1006             return null;
1007         }
1008 
1009         @Override
isPresent(int nativeHandle)1010         public boolean isPresent(int nativeHandle) throws RemoteException {
1011             TagEndpoint tag = null;
1012 
1013             // Check if NFC is enabled
1014             if (!isNfcEnabled()) {
1015                 return false;
1016             }
1017 
1018             /* find the tag in the hmap */
1019             tag = (TagEndpoint) findObject(nativeHandle);
1020             if (tag == null) {
1021                 return false;
1022             }
1023 
1024             return tag.isPresent();
1025         }
1026 
1027         @Override
isNdef(int nativeHandle)1028         public boolean isNdef(int nativeHandle) throws RemoteException {
1029             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1030 
1031             TagEndpoint tag = null;
1032 
1033             // Check if NFC is enabled
1034             if (!isNfcEnabled()) {
1035                 return false;
1036             }
1037 
1038             /* find the tag in the hmap */
1039             tag = (TagEndpoint) findObject(nativeHandle);
1040             int[] ndefInfo = new int[2];
1041             if (tag == null) {
1042                 return false;
1043             }
1044             return tag.checkNdef(ndefInfo);
1045         }
1046 
1047         @Override
transceive(int nativeHandle, byte[] data, boolean raw)1048         public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
1049                 throws RemoteException {
1050             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1051 
1052             TagEndpoint tag = null;
1053             byte[] response;
1054 
1055             // Check if NFC is enabled
1056             if (!isNfcEnabled()) {
1057                 return null;
1058             }
1059 
1060             /* find the tag in the hmap */
1061             tag = (TagEndpoint) findObject(nativeHandle);
1062             if (tag != null) {
1063                 // Check if length is within limits
1064                 if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
1065                     return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
1066                 }
1067                 int[] targetLost = new int[1];
1068                 response = tag.transceive(data, raw, targetLost);
1069                 int result;
1070                 if (response != null) {
1071                     result = TransceiveResult.RESULT_SUCCESS;
1072                 } else if (targetLost[0] == 1) {
1073                     result = TransceiveResult.RESULT_TAGLOST;
1074                 } else {
1075                     result = TransceiveResult.RESULT_FAILURE;
1076                 }
1077                 return new TransceiveResult(result, response);
1078             }
1079             return null;
1080         }
1081 
1082         @Override
ndefRead(int nativeHandle)1083         public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
1084             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1085 
1086             TagEndpoint tag;
1087 
1088             // Check if NFC is enabled
1089             if (!isNfcEnabled()) {
1090                 return null;
1091             }
1092 
1093             /* find the tag in the hmap */
1094             tag = (TagEndpoint) findObject(nativeHandle);
1095             if (tag != null) {
1096                 byte[] buf = tag.readNdef();
1097                 if (buf == null) {
1098                     return null;
1099                 }
1100 
1101                 /* Create an NdefMessage */
1102                 try {
1103                     return new NdefMessage(buf);
1104                 } catch (FormatException e) {
1105                     return null;
1106                 }
1107             }
1108             return null;
1109         }
1110 
1111         @Override
ndefWrite(int nativeHandle, NdefMessage msg)1112         public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
1113             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1114 
1115             TagEndpoint tag;
1116 
1117             // Check if NFC is enabled
1118             if (!isNfcEnabled()) {
1119                 return ErrorCodes.ERROR_NOT_INITIALIZED;
1120             }
1121 
1122             /* find the tag in the hmap */
1123             tag = (TagEndpoint) findObject(nativeHandle);
1124             if (tag == null) {
1125                 return ErrorCodes.ERROR_IO;
1126             }
1127 
1128             if (msg == null) return ErrorCodes.ERROR_INVALID_PARAM;
1129 
1130             if (tag.writeNdef(msg.toByteArray())) {
1131                 return ErrorCodes.SUCCESS;
1132             } else {
1133                 return ErrorCodes.ERROR_IO;
1134             }
1135 
1136         }
1137 
1138         @Override
ndefIsWritable(int nativeHandle)1139         public boolean ndefIsWritable(int nativeHandle) throws RemoteException {
1140             throw new UnsupportedOperationException();
1141         }
1142 
1143         @Override
ndefMakeReadOnly(int nativeHandle)1144         public int ndefMakeReadOnly(int nativeHandle) throws RemoteException {
1145             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1146 
1147             TagEndpoint tag;
1148 
1149             // Check if NFC is enabled
1150             if (!isNfcEnabled()) {
1151                 return ErrorCodes.ERROR_NOT_INITIALIZED;
1152             }
1153 
1154             /* find the tag in the hmap */
1155             tag = (TagEndpoint) findObject(nativeHandle);
1156             if (tag == null) {
1157                 return ErrorCodes.ERROR_IO;
1158             }
1159 
1160             if (tag.makeReadOnly()) {
1161                 return ErrorCodes.SUCCESS;
1162             } else {
1163                 return ErrorCodes.ERROR_IO;
1164             }
1165         }
1166 
1167         @Override
formatNdef(int nativeHandle, byte[] key)1168         public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
1169             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1170 
1171             TagEndpoint tag;
1172 
1173             // Check if NFC is enabled
1174             if (!isNfcEnabled()) {
1175                 return ErrorCodes.ERROR_NOT_INITIALIZED;
1176             }
1177 
1178             /* find the tag in the hmap */
1179             tag = (TagEndpoint) findObject(nativeHandle);
1180             if (tag == null) {
1181                 return ErrorCodes.ERROR_IO;
1182             }
1183 
1184             if (tag.formatNdef(key)) {
1185                 return ErrorCodes.SUCCESS;
1186             } else {
1187                 return ErrorCodes.ERROR_IO;
1188             }
1189         }
1190 
1191         @Override
rediscover(int nativeHandle)1192         public Tag rediscover(int nativeHandle) throws RemoteException {
1193             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1194 
1195             TagEndpoint tag = null;
1196 
1197             // Check if NFC is enabled
1198             if (!isNfcEnabled()) {
1199                 return null;
1200             }
1201 
1202             /* find the tag in the hmap */
1203             tag = (TagEndpoint) findObject(nativeHandle);
1204             if (tag != null) {
1205                 // For now the prime usecase for rediscover() is to be able
1206                 // to access the NDEF technology after formatting without
1207                 // having to remove the tag from the field, or similar
1208                 // to have access to NdefFormatable in case low-level commands
1209                 // were used to remove NDEF. So instead of doing a full stack
1210                 // rediscover (which is poorly supported at the moment anyway),
1211                 // we simply remove these two technologies and detect them
1212                 // again.
1213                 tag.removeTechnology(TagTechnology.NDEF);
1214                 tag.removeTechnology(TagTechnology.NDEF_FORMATABLE);
1215                 tag.findAndReadNdef();
1216                 // Build a new Tag object to return
1217                 Tag newTag = new Tag(tag.getUid(), tag.getTechList(),
1218                         tag.getTechExtras(), tag.getHandle(), this);
1219                 return newTag;
1220             }
1221             return null;
1222         }
1223 
1224         @Override
setTimeout(int tech, int timeout)1225         public int setTimeout(int tech, int timeout) throws RemoteException {
1226             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1227             boolean success = mDeviceHost.setTimeout(tech, timeout);
1228             if (success) {
1229                 return ErrorCodes.SUCCESS;
1230             } else {
1231                 return ErrorCodes.ERROR_INVALID_PARAM;
1232             }
1233         }
1234 
1235         @Override
getTimeout(int tech)1236         public int getTimeout(int tech) throws RemoteException {
1237             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1238 
1239             return mDeviceHost.getTimeout(tech);
1240         }
1241 
1242         @Override
resetTimeouts()1243         public void resetTimeouts() throws RemoteException {
1244             mContext.enforceCallingOrSelfPermission(NFC_PERM, NFC_PERM_ERROR);
1245 
1246             mDeviceHost.resetTimeouts();
1247         }
1248 
1249         @Override
canMakeReadOnly(int ndefType)1250         public boolean canMakeReadOnly(int ndefType) throws RemoteException {
1251             return mDeviceHost.canMakeReadOnly(ndefType);
1252         }
1253 
1254         @Override
getMaxTransceiveLength(int tech)1255         public int getMaxTransceiveLength(int tech) throws RemoteException {
1256             return mDeviceHost.getMaxTransceiveLength(tech);
1257         }
1258 
1259         @Override
getExtendedLengthApdusSupported()1260         public boolean getExtendedLengthApdusSupported() throws RemoteException {
1261             return mDeviceHost.getExtendedLengthApdusSupported();
1262         }
1263     }
1264 
_nfcEeClose(int callingPid, IBinder binder)1265     void _nfcEeClose(int callingPid, IBinder binder) throws IOException {
1266         // Blocks until a pending open() or transceive() times out.
1267         //TODO: This is incorrect behavior - the close should interrupt pending
1268         // operations. However this is not supported by current hardware.
1269 
1270         synchronized (NfcService.this) {
1271             if (!isNfcEnabledOrShuttingDown()) {
1272                 throw new IOException("NFC adapter is disabled");
1273             }
1274             if (mOpenEe == null) {
1275                 throw new IOException("NFC EE closed");
1276             }
1277             if (callingPid != -1 && callingPid != mOpenEe.pid) {
1278                 throw new SecurityException("Wrong PID");
1279             }
1280             if (mOpenEe.binder != binder) {
1281                 throw new SecurityException("Wrong binder handle");
1282             }
1283 
1284             binder.unlinkToDeath(mOpenEe, 0);
1285             mDeviceHost.resetTimeouts();
1286             doDisconnect(mOpenEe.handle);
1287             mOpenEe = null;
1288 
1289             applyRouting(true);
1290         }
1291     }
1292 
1293     final class NfcAdapterExtrasService extends INfcAdapterExtras.Stub {
writeNoException()1294         private Bundle writeNoException() {
1295             Bundle p = new Bundle();
1296             p.putInt("e", 0);
1297             return p;
1298         }
writeIoException(IOException e)1299         private Bundle writeIoException(IOException e) {
1300             Bundle p = new Bundle();
1301             p.putInt("e", -1);
1302             p.putString("m", e.getMessage());
1303             return p;
1304         }
1305 
1306         @Override
open(String pkg, IBinder b)1307         public Bundle open(String pkg, IBinder b) throws RemoteException {
1308             NfcService.this.enforceNfceeAdminPerm(pkg);
1309 
1310             Bundle result;
1311             try {
1312                 _open(b);
1313                 result = writeNoException();
1314             } catch (IOException e) {
1315                 result = writeIoException(e);
1316             }
1317             return result;
1318         }
1319 
_open(IBinder b)1320         private void _open(IBinder b) throws IOException {
1321             synchronized(NfcService.this) {
1322                 if (!isNfcEnabled()) {
1323                     throw new IOException("NFC adapter is disabled");
1324                 }
1325                 if (mOpenEe != null) {
1326                     throw new IOException("NFC EE already open");
1327                 }
1328 
1329                 int handle = doOpenSecureElementConnection();
1330                 if (handle == 0) {
1331                     throw new IOException("NFC EE failed to open");
1332                 }
1333                 mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000);
1334 
1335                 mOpenEe = new OpenSecureElement(getCallingPid(), handle, b);
1336                 try {
1337                     b.linkToDeath(mOpenEe, 0);
1338                 } catch (RemoteException e) {
1339                     mOpenEe.binderDied();
1340                 }
1341 
1342                 // Add the calling package to the list of packages that have accessed
1343                 // the secure element.
1344                 for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
1345                     mSePackages.add(packageName);
1346                 }
1347            }
1348         }
1349 
1350         @Override
close(String pkg, IBinder binder)1351         public Bundle close(String pkg, IBinder binder) throws RemoteException {
1352             NfcService.this.enforceNfceeAdminPerm(pkg);
1353 
1354             Bundle result;
1355             try {
1356                 _nfcEeClose(getCallingPid(), binder);
1357                 result = writeNoException();
1358             } catch (IOException e) {
1359                 result = writeIoException(e);
1360             }
1361             return result;
1362         }
1363 
1364         @Override
transceive(String pkg, byte[] in)1365         public Bundle transceive(String pkg, byte[] in) throws RemoteException {
1366             NfcService.this.enforceNfceeAdminPerm(pkg);
1367 
1368             Bundle result;
1369             byte[] out;
1370             try {
1371                 out = _transceive(in);
1372                 result = writeNoException();
1373                 result.putByteArray("out", out);
1374             } catch (IOException e) {
1375                 result = writeIoException(e);
1376             }
1377             return result;
1378         }
1379 
_transceive(byte[] data)1380         private byte[] _transceive(byte[] data) throws IOException {
1381             synchronized(NfcService.this) {
1382                 if (!isNfcEnabled()) {
1383                     throw new IOException("NFC is not enabled");
1384                 }
1385                 if (mOpenEe == null) {
1386                     throw new IOException("NFC EE is not open");
1387                 }
1388                 if (getCallingPid() != mOpenEe.pid) {
1389                     throw new SecurityException("Wrong PID");
1390                 }
1391             }
1392 
1393             return doTransceive(mOpenEe.handle, data);
1394         }
1395 
1396         @Override
getCardEmulationRoute(String pkg)1397         public int getCardEmulationRoute(String pkg) throws RemoteException {
1398             NfcService.this.enforceNfceeAdminPerm(pkg);
1399             return mEeRoutingState;
1400         }
1401 
1402         @Override
setCardEmulationRoute(String pkg, int route)1403         public void setCardEmulationRoute(String pkg, int route) throws RemoteException {
1404             NfcService.this.enforceNfceeAdminPerm(pkg);
1405             mEeRoutingState = route;
1406             ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask();
1407             applyRoutingTask.execute();
1408             try {
1409                 // Block until route is set
1410                 applyRoutingTask.get();
1411             } catch (ExecutionException e) {
1412                 Log.e(TAG, "failed to set card emulation mode");
1413             } catch (InterruptedException e) {
1414                 Log.e(TAG, "failed to set card emulation mode");
1415             }
1416         }
1417 
1418         @Override
authenticate(String pkg, byte[] token)1419         public void authenticate(String pkg, byte[] token) throws RemoteException {
1420             NfcService.this.enforceNfceeAdminPerm(pkg);
1421         }
1422 
1423         @Override
getDriverName(String pkg)1424         public String getDriverName(String pkg) throws RemoteException {
1425             NfcService.this.enforceNfceeAdminPerm(pkg);
1426             return mDeviceHost.getName();
1427         }
1428     }
1429 
1430     /** resources kept while secure element is open */
1431     private class OpenSecureElement implements IBinder.DeathRecipient {
1432         public int pid;  // pid that opened SE
1433         // binder handle used for DeathReceipient. Must keep
1434         // a reference to this, otherwise it can get GC'd and
1435         // the binder stub code might create a different BinderProxy
1436         // for the same remote IBinder, causing mismatched
1437         // link()/unlink()
1438         public IBinder binder;
1439         public int handle; // low-level handle
OpenSecureElement(int pid, int handle, IBinder binder)1440         public OpenSecureElement(int pid, int handle, IBinder binder) {
1441             this.pid = pid;
1442             this.handle = handle;
1443             this.binder = binder;
1444         }
1445         @Override
binderDied()1446         public void binderDied() {
1447             synchronized (NfcService.this) {
1448                 Log.i(TAG, "Tracked app " + pid + " died");
1449                 pid = -1;
1450                 try {
1451                     _nfcEeClose(-1, binder);
1452                 } catch (IOException e) { /* already closed */ }
1453             }
1454         }
1455         @Override
toString()1456         public String toString() {
1457             return new StringBuilder('@').append(Integer.toHexString(hashCode())).append("[pid=")
1458                     .append(pid).append(" handle=").append(handle).append("]").toString();
1459         }
1460     }
1461 
isNfcEnabledOrShuttingDown()1462     boolean isNfcEnabledOrShuttingDown() {
1463         synchronized (this) {
1464             return (mState == NfcAdapter.STATE_ON || mState == NfcAdapter.STATE_TURNING_OFF);
1465         }
1466     }
1467 
isNfcEnabled()1468     boolean isNfcEnabled() {
1469         synchronized (this) {
1470             return mState == NfcAdapter.STATE_ON;
1471         }
1472     }
1473 
1474     class WatchDogThread extends Thread {
1475         boolean mWatchDogCanceled = false;
1476         final int mTimeout;
1477 
WatchDogThread(String threadName, int timeout)1478         public WatchDogThread(String threadName, int timeout) {
1479             super(threadName);
1480             mTimeout = timeout;
1481         }
1482 
1483         @Override
run()1484         public void run() {
1485             boolean slept = false;
1486             while (!slept) {
1487                 try {
1488                     Thread.sleep(mTimeout);
1489                     slept = true;
1490                 } catch (InterruptedException e) { }
1491             }
1492             synchronized (this) {
1493                 if (!mWatchDogCanceled) {
1494                     // Trigger watch-dog
1495                     Log.e(TAG, "Watchdog fired: name=" + getName() + " threadId=" +
1496                             getId() + " timeout=" + mTimeout);
1497                     mDeviceHost.doAbort();
1498                 }
1499             }
1500         }
cancel()1501         public synchronized void cancel() {
1502             mWatchDogCanceled = true;
1503         }
1504     }
1505 
1506     /**
1507      * Read mScreenState and apply NFC-C polling and NFC-EE routing
1508      */
applyRouting(boolean force)1509     void applyRouting(boolean force) {
1510         synchronized (this) {
1511             if (!isNfcEnabledOrShuttingDown() || mOpenEe != null) {
1512                 // PN544 cannot be reconfigured while EE is open
1513                 return;
1514             }
1515             WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS);
1516 
1517             try {
1518                 watchDog.start();
1519 
1520                 if (mDeviceHost.enablePN544Quirks() && mScreenState == SCREEN_STATE_OFF) {
1521                     /* TODO undo this after the LLCP stack is fixed.
1522                      * Use a different sequence when turning the screen off to
1523                      * workaround race conditions in pn544 libnfc. The race occurs
1524                      * when we change routing while there is a P2P target connect.
1525                      * The async LLCP callback will crash since the routing code
1526                      * is overwriting globals it relies on.
1527                      */
1528                     if (POLLING_MODE > SCREEN_STATE_OFF) {
1529                         if (force || mNfcPollingEnabled) {
1530                             Log.d(TAG, "NFC-C OFF, disconnect");
1531                             mNfcPollingEnabled = false;
1532                             mDeviceHost.disableDiscovery();
1533                             maybeDisconnectTarget();
1534                         }
1535                     }
1536                     if (mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
1537                         if (force || mNfceeRouteEnabled) {
1538                             Log.d(TAG, "NFC-EE OFF");
1539                             mNfceeRouteEnabled = false;
1540                             mDeviceHost.doDeselectSecureElement();
1541                         }
1542                     }
1543                     return;
1544                 }
1545 
1546                 // configure NFC-EE routing
1547                 if (mScreenState >= SCREEN_STATE_ON_LOCKED &&
1548                         mEeRoutingState == ROUTE_ON_WHEN_SCREEN_ON) {
1549                     if (force || !mNfceeRouteEnabled) {
1550                         Log.d(TAG, "NFC-EE ON");
1551                         mNfceeRouteEnabled = true;
1552                         mDeviceHost.doSelectSecureElement();
1553                     }
1554                 } else {
1555                     if (force ||  mNfceeRouteEnabled) {
1556                         Log.d(TAG, "NFC-EE OFF");
1557                         mNfceeRouteEnabled = false;
1558                         mDeviceHost.doDeselectSecureElement();
1559                     }
1560                 }
1561 
1562                 // configure NFC-C polling
1563                 if (mScreenState >= POLLING_MODE) {
1564                     if (force || !mNfcPollingEnabled) {
1565                         Log.d(TAG, "NFC-C ON");
1566                         mNfcPollingEnabled = true;
1567                         mDeviceHost.enableDiscovery();
1568                     }
1569                 } else {
1570                     if (force || mNfcPollingEnabled) {
1571                         Log.d(TAG, "NFC-C OFF");
1572                         mNfcPollingEnabled = false;
1573                         mDeviceHost.disableDiscovery();
1574                     }
1575                 }
1576             } finally {
1577                 watchDog.cancel();
1578             }
1579         }
1580     }
1581 
1582     /** Disconnect any target if present */
maybeDisconnectTarget()1583     void maybeDisconnectTarget() {
1584         if (!isNfcEnabledOrShuttingDown()) {
1585             return;
1586         }
1587         Object[] objectsToDisconnect;
1588         synchronized (this) {
1589             Object[] objectValues = mObjectMap.values().toArray();
1590             // Copy the array before we clear mObjectMap,
1591             // just in case the HashMap values are backed by the same array
1592             objectsToDisconnect = Arrays.copyOf(objectValues, objectValues.length);
1593             mObjectMap.clear();
1594         }
1595         for (Object o : objectsToDisconnect) {
1596             if (DBG) Log.d(TAG, "disconnecting " + o.getClass().getName());
1597             if (o instanceof TagEndpoint) {
1598                 // Disconnect from tags
1599                 TagEndpoint tag = (TagEndpoint) o;
1600                 tag.disconnect();
1601             } else if (o instanceof NfcDepEndpoint) {
1602                 // Disconnect from P2P devices
1603                 NfcDepEndpoint device = (NfcDepEndpoint) o;
1604                 if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
1605                     // Remote peer is target, request disconnection
1606                     device.disconnect();
1607                 } else {
1608                     // Remote peer is initiator, we cannot disconnect
1609                     // Just wait for field removal
1610                 }
1611             }
1612         }
1613     }
1614 
findObject(int key)1615     Object findObject(int key) {
1616         synchronized (this) {
1617             Object device = mObjectMap.get(key);
1618             if (device == null) {
1619                 Log.w(TAG, "Handle not found");
1620             }
1621             return device;
1622         }
1623     }
1624 
registerTagObject(TagEndpoint tag)1625     void registerTagObject(TagEndpoint tag) {
1626         synchronized (this) {
1627             mObjectMap.put(tag.getHandle(), tag);
1628         }
1629     }
1630 
unregisterObject(int handle)1631     void unregisterObject(int handle) {
1632         synchronized (this) {
1633             mObjectMap.remove(handle);
1634         }
1635     }
1636 
1637     /** For use by code in this process */
createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)1638     public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
1639             throws LlcpException {
1640         return mDeviceHost.createLlcpSocket(sap, miu, rw, linearBufferLength);
1641     }
1642 
1643     /** For use by code in this process */
createLlcpConnectionLessSocket(int sap, String sn)1644     public LlcpConnectionlessSocket createLlcpConnectionLessSocket(int sap, String sn)
1645             throws LlcpException {
1646         return mDeviceHost.createLlcpConnectionlessSocket(sap, sn);
1647     }
1648 
1649     /** For use by code in this process */
createLlcpServerSocket(int sap, String sn, int miu, int rw, int linearBufferLength)1650     public LlcpServerSocket createLlcpServerSocket(int sap, String sn, int miu, int rw,
1651             int linearBufferLength) throws LlcpException {
1652         return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength);
1653     }
1654 
sendMockNdefTag(NdefMessage msg)1655     public void sendMockNdefTag(NdefMessage msg) {
1656         sendMessage(MSG_MOCK_NDEF, msg);
1657     }
1658 
sendMessage(int what, Object obj)1659     void sendMessage(int what, Object obj) {
1660         Message msg = mHandler.obtainMessage();
1661         msg.what = what;
1662         msg.obj = obj;
1663         mHandler.sendMessage(msg);
1664     }
1665 
1666     final class NfcServiceHandler extends Handler {
1667         @Override
handleMessage(Message msg)1668         public void handleMessage(Message msg) {
1669             switch (msg.what) {
1670                 case MSG_MOCK_NDEF: {
1671                     NdefMessage ndefMsg = (NdefMessage) msg.obj;
1672                     Bundle extras = new Bundle();
1673                     extras.putParcelable(Ndef.EXTRA_NDEF_MSG, ndefMsg);
1674                     extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, 0);
1675                     extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, Ndef.NDEF_MODE_READ_ONLY);
1676                     extras.putInt(Ndef.EXTRA_NDEF_TYPE, Ndef.TYPE_OTHER);
1677                     Tag tag = Tag.createMockTag(new byte[] { 0x00 },
1678                             new int[] { TagTechnology.NDEF },
1679                             new Bundle[] { extras });
1680                     Log.d(TAG, "mock NDEF tag, starting corresponding activity");
1681                     Log.d(TAG, tag.toString());
1682                     boolean delivered = mNfcDispatcher.dispatchTag(tag);
1683                     if (delivered) {
1684                         playSound(SOUND_END);
1685                     } else {
1686                         playSound(SOUND_ERROR);
1687                     }
1688                     break;
1689                 }
1690 
1691                 case MSG_NDEF_TAG:
1692                     if (DBG) Log.d(TAG, "Tag detected, notifying applications");
1693                     TagEndpoint tag = (TagEndpoint) msg.obj;
1694                     playSound(SOUND_START);
1695                     NdefMessage ndefMsg = tag.findAndReadNdef();
1696 
1697                     if (ndefMsg != null) {
1698                         tag.startPresenceChecking();
1699                         dispatchTagEndpoint(tag);
1700                     } else {
1701                         if (tag.reconnect()) {
1702                             tag.startPresenceChecking();
1703                             dispatchTagEndpoint(tag);
1704                         } else {
1705                             tag.disconnect();
1706                             playSound(SOUND_ERROR);
1707                         }
1708                     }
1709                     break;
1710 
1711                 case MSG_CARD_EMULATION:
1712                     if (DBG) Log.d(TAG, "Card Emulation message");
1713                     byte[] aid = (byte[]) msg.obj;
1714                     /* Send broadcast */
1715                     Intent aidIntent = new Intent();
1716                     aidIntent.setAction(ACTION_AID_SELECTED);
1717                     aidIntent.putExtra(EXTRA_AID, aid);
1718                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_AID_SELECTED);
1719                     sendSeBroadcast(aidIntent);
1720                     break;
1721 
1722                 case MSG_SE_EMV_CARD_REMOVAL:
1723                     if (DBG) Log.d(TAG, "Card Removal message");
1724                     /* Send broadcast */
1725                     Intent cardRemovalIntent = new Intent();
1726                     cardRemovalIntent.setAction(ACTION_EMV_CARD_REMOVAL);
1727                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_EMV_CARD_REMOVAL);
1728                     sendSeBroadcast(cardRemovalIntent);
1729                     break;
1730 
1731                 case MSG_SE_APDU_RECEIVED:
1732                     if (DBG) Log.d(TAG, "APDU Received message");
1733                     byte[] apduBytes = (byte[]) msg.obj;
1734                     /* Send broadcast */
1735                     Intent apduReceivedIntent = new Intent();
1736                     apduReceivedIntent.setAction(ACTION_APDU_RECEIVED);
1737                     if (apduBytes != null && apduBytes.length > 0) {
1738                         apduReceivedIntent.putExtra(EXTRA_APDU_BYTES, apduBytes);
1739                     }
1740                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_APDU_RECEIVED);
1741                     sendSeBroadcast(apduReceivedIntent);
1742                     break;
1743 
1744                 case MSG_SE_MIFARE_ACCESS:
1745                     if (DBG) Log.d(TAG, "MIFARE access message");
1746                     /* Send broadcast */
1747                     byte[] mifareCmd = (byte[]) msg.obj;
1748                     Intent mifareAccessIntent = new Intent();
1749                     mifareAccessIntent.setAction(ACTION_MIFARE_ACCESS_DETECTED);
1750                     if (mifareCmd != null && mifareCmd.length > 1) {
1751                         int mifareBlock = mifareCmd[1] & 0xff;
1752                         if (DBG) Log.d(TAG, "Mifare Block=" + mifareBlock);
1753                         mifareAccessIntent.putExtra(EXTRA_MIFARE_BLOCK, mifareBlock);
1754                     }
1755                     if (DBG) Log.d(TAG, "Broadcasting " + ACTION_MIFARE_ACCESS_DETECTED);
1756                     sendSeBroadcast(mifareAccessIntent);
1757                     break;
1758 
1759                 case MSG_LLCP_LINK_ACTIVATION:
1760                     llcpActivated((NfcDepEndpoint) msg.obj);
1761                     break;
1762 
1763                 case MSG_LLCP_LINK_DEACTIVATED:
1764                     NfcDepEndpoint device = (NfcDepEndpoint) msg.obj;
1765                     boolean needsDisconnect = false;
1766 
1767                     Log.d(TAG, "LLCP Link Deactivated message. Restart polling loop.");
1768                     synchronized (NfcService.this) {
1769                         /* Check if the device has been already unregistered */
1770                         if (mObjectMap.remove(device.getHandle()) != null) {
1771                             /* Disconnect if we are initiator */
1772                             if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
1773                                 if (DBG) Log.d(TAG, "disconnecting from target");
1774                                 needsDisconnect = true;
1775                             } else {
1776                                 if (DBG) Log.d(TAG, "not disconnecting from initiator");
1777                             }
1778                         }
1779                     }
1780                     if (needsDisconnect) {
1781                         device.disconnect();  // restarts polling loop
1782                     }
1783 
1784                     mP2pLinkManager.onLlcpDeactivated();
1785                     break;
1786 
1787                 case MSG_TARGET_DESELECTED:
1788                     /* Broadcast Intent Target Deselected */
1789                     if (DBG) Log.d(TAG, "Target Deselected");
1790                     Intent intent = new Intent();
1791                     intent.setAction(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
1792                     if (DBG) Log.d(TAG, "Broadcasting Intent");
1793                     mContext.sendOrderedBroadcast(intent, NFC_PERM);
1794                     break;
1795 
1796                 case MSG_SE_FIELD_ACTIVATED: {
1797                     if (DBG) Log.d(TAG, "SE FIELD ACTIVATED");
1798                     Intent eventFieldOnIntent = new Intent();
1799                     eventFieldOnIntent.setAction(ACTION_RF_FIELD_ON_DETECTED);
1800                     sendSeBroadcast(eventFieldOnIntent);
1801                     break;
1802                 }
1803 
1804                 case MSG_SE_FIELD_DEACTIVATED: {
1805                     if (DBG) Log.d(TAG, "SE FIELD DEACTIVATED");
1806                     Intent eventFieldOffIntent = new Intent();
1807                     eventFieldOffIntent.setAction(ACTION_RF_FIELD_OFF_DETECTED);
1808                     sendSeBroadcast(eventFieldOffIntent);
1809                     break;
1810                 }
1811 
1812                 case MSG_SE_LISTEN_ACTIVATED: {
1813                     if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED");
1814                     Intent listenModeActivated = new Intent();
1815                     listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED);
1816                     sendSeBroadcast(listenModeActivated);
1817                     break;
1818                 }
1819 
1820                 case MSG_SE_LISTEN_DEACTIVATED: {
1821                     if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED");
1822                     Intent listenModeDeactivated = new Intent();
1823                     listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED);
1824                     sendSeBroadcast(listenModeDeactivated);
1825                     break;
1826                 }
1827 
1828                 default:
1829                     Log.e(TAG, "Unknown message received");
1830                     break;
1831             }
1832         }
1833 
sendSeBroadcast(Intent intent)1834         private void sendSeBroadcast(Intent intent) {
1835             intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
1836             // Resume app switches so the receivers can start activites without delay
1837             mNfcDispatcher.resumeAppSwitches();
1838 
1839             synchronized(this) {
1840                 for (PackageInfo pkg : mInstalledPackages) {
1841                     if (pkg != null && pkg.applicationInfo != null) {
1842                         if (mNfceeAccessControl.check(pkg.applicationInfo)) {
1843                             intent.setPackage(pkg.packageName);
1844                             mContext.sendBroadcast(intent);
1845                         }
1846                     }
1847                 }
1848             }
1849         }
1850 
llcpActivated(NfcDepEndpoint device)1851         private boolean llcpActivated(NfcDepEndpoint device) {
1852             Log.d(TAG, "LLCP Activation message");
1853 
1854             if (device.getMode() == NfcDepEndpoint.MODE_P2P_TARGET) {
1855                 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_TARGET");
1856                 if (device.connect()) {
1857                     /* Check LLCP compliancy */
1858                     if (mDeviceHost.doCheckLlcp()) {
1859                         /* Activate LLCP Link */
1860                         if (mDeviceHost.doActivateLlcp()) {
1861                             if (DBG) Log.d(TAG, "Initiator Activate LLCP OK");
1862                             synchronized (NfcService.this) {
1863                                 // Register P2P device
1864                                 mObjectMap.put(device.getHandle(), device);
1865                             }
1866                             mP2pLinkManager.onLlcpActivated();
1867                             return true;
1868                         } else {
1869                             /* should not happen */
1870                             Log.w(TAG, "Initiator LLCP activation failed. Disconnect.");
1871                             device.disconnect();
1872                         }
1873                     } else {
1874                         if (DBG) Log.d(TAG, "Remote Target does not support LLCP. Disconnect.");
1875                         device.disconnect();
1876                     }
1877                 } else {
1878                     if (DBG) Log.d(TAG, "Cannot connect remote Target. Polling loop restarted.");
1879                     /*
1880                      * The polling loop should have been restarted in failing
1881                      * doConnect
1882                      */
1883                 }
1884             } else if (device.getMode() == NfcDepEndpoint.MODE_P2P_INITIATOR) {
1885                 if (DBG) Log.d(TAG, "NativeP2pDevice.MODE_P2P_INITIATOR");
1886                 /* Check LLCP compliancy */
1887                 if (mDeviceHost.doCheckLlcp()) {
1888                     /* Activate LLCP Link */
1889                     if (mDeviceHost.doActivateLlcp()) {
1890                         if (DBG) Log.d(TAG, "Target Activate LLCP OK");
1891                         synchronized (NfcService.this) {
1892                             // Register P2P device
1893                             mObjectMap.put(device.getHandle(), device);
1894                         }
1895                         mP2pLinkManager.onLlcpActivated();
1896                         return true;
1897                     }
1898                 } else {
1899                     Log.w(TAG, "checkLlcp failed");
1900                 }
1901             }
1902 
1903             return false;
1904         }
1905 
dispatchTagEndpoint(TagEndpoint tagEndpoint)1906         private void dispatchTagEndpoint(TagEndpoint tagEndpoint) {
1907             Tag tag = new Tag(tagEndpoint.getUid(), tagEndpoint.getTechList(),
1908                     tagEndpoint.getTechExtras(), tagEndpoint.getHandle(), mNfcTagService);
1909             registerTagObject(tagEndpoint);
1910             if (!mNfcDispatcher.dispatchTag(tag)) {
1911                 unregisterObject(tagEndpoint.getHandle());
1912                 playSound(SOUND_ERROR);
1913             } else {
1914                 playSound(SOUND_END);
1915             }
1916         }
1917     }
1918 
1919     private NfcServiceHandler mHandler = new NfcServiceHandler();
1920 
1921     class ApplyRoutingTask extends AsyncTask<Integer, Void, Void> {
1922         @Override
doInBackground(Integer... params)1923         protected Void doInBackground(Integer... params) {
1924             synchronized (NfcService.this) {
1925                 if (params == null || params.length != 1) {
1926                     // force apply current routing
1927                     applyRouting(true);
1928                     return null;
1929                 }
1930                 mScreenState = params[0].intValue();
1931 
1932                 mRoutingWakeLock.acquire();
1933                 try {
1934                     applyRouting(false);
1935                 } finally {
1936                     mRoutingWakeLock.release();
1937                 }
1938                 return null;
1939             }
1940         }
1941     }
1942 
1943     private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
1944         @Override
1945         public void onReceive(Context context, Intent intent) {
1946             String action = intent.getAction();
1947             if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
1948                     action.equals(Intent.ACTION_PACKAGE_ADDED) ||
1949                     action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
1950                     action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
1951                 updatePackageCache();
1952 
1953                 if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
1954                     // Clear the NFCEE access cache in case a UID gets recycled
1955                     mNfceeAccessControl.invalidateCache();
1956 
1957                     boolean dataRemoved = intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);
1958                     if (dataRemoved) {
1959                         Uri data = intent.getData();
1960                         if (data == null) return;
1961                         String packageName = data.getSchemeSpecificPart();
1962 
1963                         synchronized (NfcService.this) {
1964                             if (mSePackages.contains(packageName)) {
1965                                 new EnableDisableTask().execute(TASK_EE_WIPE);
1966                                 mSePackages.remove(packageName);
1967                             }
1968                         }
1969                     }
1970                 }
1971             } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
1972                 EnableDisableTask eeWipeTask = new EnableDisableTask();
1973                 eeWipeTask.execute(TASK_EE_WIPE);
1974                 try {
1975                     eeWipeTask.get();  // blocks until EE wipe is complete
1976                 } catch (ExecutionException e) {
1977                     Log.w(TAG, "failed to wipe NFC-EE");
1978                 } catch (InterruptedException e) {
1979                     Log.w(TAG, "failed to wipe NFC-EE");
1980                 }
1981             }
1982         }
1983     };
1984 
1985     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
1986         @Override
1987         public void onReceive(Context context, Intent intent) {
1988             String action = intent.getAction();
1989             if (action.equals(
1990                     NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
1991                 // Perform applyRouting() in AsyncTask to serialize blocking calls
1992                 new ApplyRoutingTask().execute();
1993             } else if (action.equals(Intent.ACTION_SCREEN_ON)
1994                     || action.equals(Intent.ACTION_SCREEN_OFF)
1995                     || action.equals(Intent.ACTION_USER_PRESENT)) {
1996                 // Perform applyRouting() in AsyncTask to serialize blocking calls
1997                 int screenState = SCREEN_STATE_OFF;
1998                 if (action.equals(Intent.ACTION_SCREEN_OFF)) {
1999                     screenState = SCREEN_STATE_OFF;
2000                 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
2001                     screenState = mKeyguard.isKeyguardLocked() ?
2002                             SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
2003                 } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
2004                     screenState = SCREEN_STATE_ON_UNLOCKED;
2005                 }
2006                 new ApplyRoutingTask().execute(Integer.valueOf(screenState));
2007             } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
2008                 boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
2009                 // Query the airplane mode from Settings.System just to make sure that
2010                 // some random app is not sending this intent
2011                 if (isAirplaneModeOn != isAirplaneModeOn()) {
2012                     return;
2013                 }
2014                 if (!mIsAirplaneSensitive) {
2015                     return;
2016                 }
2017                 mPrefsEditor.putBoolean(PREF_AIRPLANE_OVERRIDE, false);
2018                 mPrefsEditor.apply();
2019                 if (isAirplaneModeOn) {
2020                     new EnableDisableTask().execute(TASK_DISABLE);
2021                 } else if (!isAirplaneModeOn && mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
2022                     new EnableDisableTask().execute(TASK_ENABLE);
2023                 }
2024             }
2025         }
2026     };
2027 
2028     /** Returns true if airplane mode is currently on */
isAirplaneModeOn()2029     boolean isAirplaneModeOn() {
2030         return Settings.System.getInt(mContext.getContentResolver(),
2031                 Settings.System.AIRPLANE_MODE_ON, 0) == 1;
2032     }
2033 
2034     /** for debugging only - no i18n */
stateToString(int state)2035     static String stateToString(int state) {
2036         switch (state) {
2037             case NfcAdapter.STATE_OFF:
2038                 return "off";
2039             case NfcAdapter.STATE_TURNING_ON:
2040                 return "turning on";
2041             case NfcAdapter.STATE_ON:
2042                 return "on";
2043             case NfcAdapter.STATE_TURNING_OFF:
2044                 return "turning off";
2045             default:
2046                 return "<error>";
2047         }
2048     }
2049 
2050     /** For debugging only - no i18n */
screenStateToString(int screenState)2051     static String screenStateToString(int screenState) {
2052         switch (screenState) {
2053             case SCREEN_STATE_OFF:
2054                 return "OFF";
2055             case SCREEN_STATE_ON_LOCKED:
2056                 return "ON_LOCKED";
2057             case SCREEN_STATE_ON_UNLOCKED:
2058                 return "ON_UNLOCKED";
2059             default:
2060                 return "UNKNOWN";
2061         }
2062     }
2063 
dump(FileDescriptor fd, PrintWriter pw, String[] args)2064     void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2065         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2066                 != PackageManager.PERMISSION_GRANTED) {
2067             pw.println("Permission Denial: can't dump nfc from from pid="
2068                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2069                     + " without permission " + android.Manifest.permission.DUMP);
2070             return;
2071         }
2072 
2073         synchronized (this) {
2074             pw.println("mState=" + stateToString(mState));
2075             pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled);
2076             pw.println("mScreenState=" + screenStateToString(mScreenState));
2077             pw.println("mNfcPollingEnabled=" + mNfcPollingEnabled);
2078             pw.println("mNfceeRouteEnabled=" + mNfceeRouteEnabled);
2079             pw.println("mIsAirplaneSensitive=" + mIsAirplaneSensitive);
2080             pw.println("mIsAirplaneToggleable=" + mIsAirplaneToggleable);
2081             pw.println("mOpenEe=" + mOpenEe);
2082             mP2pLinkManager.dump(fd, pw, args);
2083             mNfceeAccessControl.dump(fd, pw, args);
2084             mNfcDispatcher.dump(fd, pw, args);
2085             pw.println(mDeviceHost.dump());
2086 
2087         }
2088     }
2089 }
2090