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