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