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