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