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