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