/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.nfc;

import android.Manifest;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.os.UserManager;

import com.android.nfc.RegisteredComponentCache.ComponentInfo;
import com.android.nfc.handover.HandoverDataParser;
import com.android.nfc.handover.PeripheralHandoverService;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.IActivityManager;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcBarcode;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;

/**
 * Dispatch of NFC events to start activities
 */
class NfcDispatcher {
    private static final boolean DBG = false;
    private static final String TAG = "NfcDispatcher";

    static final int DISPATCH_SUCCESS = 1;
    static final int DISPATCH_FAIL = 2;
    static final int DISPATCH_UNLOCK = 3;

    private final Context mContext;
    private final IActivityManager mIActivityManager;
    private final RegisteredComponentCache mTechListFilters;
    private final ContentResolver mContentResolver;
    private final HandoverDataParser mHandoverDataParser;
    private final String[] mProvisioningMimes;
    private final String[] mLiveCaseMimes;
    private final ScreenStateHelper mScreenStateHelper;
    private final NfcUnlockManager mNfcUnlockManager;
    private final boolean mDeviceSupportsBluetooth;
    private final Handler mMessageHandler = new MessageHandler();
    private final Messenger mMessenger = new Messenger(mMessageHandler);
    private AtomicBoolean mBluetoothEnabledByNfc = new AtomicBoolean();

    // Locked on this
    private PendingIntent mOverrideIntent;
    private IntentFilter[] mOverrideFilters;
    private String[][] mOverrideTechLists;
    private boolean mProvisioningOnly;

    NfcDispatcher(Context context,
                  HandoverDataParser handoverDataParser,
                  boolean provisionOnly,
                  boolean isLiveCaseEnabled) {
        mContext = context;
        mIActivityManager = ActivityManager.getService();
        mTechListFilters = new RegisteredComponentCache(mContext,
                NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
        mContentResolver = context.getContentResolver();
        mHandoverDataParser = handoverDataParser;
        mScreenStateHelper = new ScreenStateHelper(context);
        mNfcUnlockManager = NfcUnlockManager.getInstance();
        mDeviceSupportsBluetooth = BluetoothAdapter.getDefaultAdapter() != null;

        synchronized (this) {
            mProvisioningOnly = provisionOnly;
        }
        String[] provisionMimes = null;
        if (provisionOnly) {
            try {
                // Get accepted mime-types
                provisionMimes = context.getResources().
                        getStringArray(R.array.provisioning_mime_types);
            } catch (NotFoundException e) {
               provisionMimes = null;
            }
        }
        mProvisioningMimes = provisionMimes;

        String[] liveCaseMimes = null;
        if (isLiveCaseEnabled) {
            try {
                // Get accepted mime-types
                liveCaseMimes = context.getResources().
                        getStringArray(R.array.live_case_mime_types);
            } catch (NotFoundException e) {
               liveCaseMimes = null;
            }
        }
        mLiveCaseMimes = liveCaseMimes;

        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        mContext.registerReceiver(mBluetoothStatusReceiver, filter);
    }

    @Override
    protected void finalize() throws Throwable {
        mContext.unregisterReceiver(mBluetoothStatusReceiver);
        super.finalize();
    }

    public synchronized void setForegroundDispatch(PendingIntent intent,
            IntentFilter[] filters, String[][] techLists) {
        if (DBG) Log.d(TAG, "Set Foreground Dispatch");
        mOverrideIntent = intent;
        mOverrideFilters = filters;
        mOverrideTechLists = techLists;
    }

    public synchronized void disableProvisioningMode() {
       mProvisioningOnly = false;
    }

    /**
     * Helper for re-used objects and methods during a single tag dispatch.
     */
    static class DispatchInfo {
        public final Intent intent;

        final Intent rootIntent;
        final Uri ndefUri;
        final String ndefMimeType;
        final PackageManager packageManager;
        final Context context;

        public DispatchInfo(Context context, Tag tag, NdefMessage message) {
            intent = new Intent();
            intent.putExtra(NfcAdapter.EXTRA_TAG, tag);
            intent.putExtra(NfcAdapter.EXTRA_ID, tag.getId());
            if (message != null) {
                intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, new NdefMessage[] {message});
                ndefUri = message.getRecords()[0].toUri();
                ndefMimeType = message.getRecords()[0].toMimeType();
            } else {
                ndefUri = null;
                ndefMimeType = null;
            }

            rootIntent = new Intent(context, NfcRootActivity.class);
            rootIntent.putExtra(NfcRootActivity.EXTRA_LAUNCH_INTENT, intent);
            rootIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

            this.context = context;
            packageManager = context.getPackageManager();
        }

        public Intent setNdefIntent() {
            intent.setAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
            if (ndefUri != null) {
                intent.setData(ndefUri);
                return intent;
            } else if (ndefMimeType != null) {
                intent.setType(ndefMimeType);
                return intent;
            }
            return null;
        }

        public Intent setTechIntent() {
            intent.setData(null);
            intent.setType(null);
            intent.setAction(NfcAdapter.ACTION_TECH_DISCOVERED);
            return intent;
        }

        public Intent setTagIntent() {
            intent.setData(null);
            intent.setType(null);
            intent.setAction(NfcAdapter.ACTION_TAG_DISCOVERED);
            return intent;
        }

        public boolean hasIntentReceiver() {
            return packageManager.queryIntentActivitiesAsUser(intent, 0,
                    ActivityManager.getCurrentUser()).size() > 0;
        }

        public boolean isWebIntent() {
            return ndefUri != null && ndefUri.normalizeScheme().getScheme() != null &&
                ndefUri.normalizeScheme().getScheme().startsWith("http");
        }

        public String getUri() {
            return ndefUri.toString();
        }

        /**
         * Launch the activity via a (single) NFC root task, so that it
         * creates a new task stack instead of interfering with any existing
         * task stack for that activity.
         * NfcRootActivity acts as the task root, it immediately calls
         * start activity on the intent it is passed.
         */
        boolean tryStartActivity() {
            // Ideally we'd have used startActivityForResult() to determine whether the
            // NfcRootActivity was able to launch the intent, but startActivityForResult()
            // is not available on Context. Instead, we query the PackageManager beforehand
            // to determine if there is an Activity to handle this intent, and base the
            // result of off that.
            List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(intent, 0,
                    ActivityManager.getCurrentUser());
            if (activities.size() > 0) {
                context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
                return true;
            }
            return false;
        }

        boolean tryStartActivity(Intent intentToStart) {
            List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(
                    intentToStart, 0, ActivityManager.getCurrentUser());
            if (activities.size() > 0) {
                rootIntent.putExtra(NfcRootActivity.EXTRA_LAUNCH_INTENT, intentToStart);
                context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
                return true;
            }
            return false;
        }
    }

    /** Returns:
     * <ul>
     *  <li /> DISPATCH_SUCCESS if dispatched to an activity,
     *  <li /> DISPATCH_FAIL if no activities were found to dispatch to,
     *  <li /> DISPATCH_UNLOCK if the tag was used to unlock the device
     * </ul>
     */
    public int dispatchTag(Tag tag) {
        PendingIntent overrideIntent;
        IntentFilter[] overrideFilters;
        String[][] overrideTechLists;
        String[] provisioningMimes;
        String[] liveCaseMimes;
        NdefMessage message = null;
        boolean provisioningOnly;

        synchronized (this) {
            overrideFilters = mOverrideFilters;
            overrideIntent = mOverrideIntent;
            overrideTechLists = mOverrideTechLists;
            provisioningOnly = mProvisioningOnly;
            provisioningMimes = mProvisioningMimes;
            liveCaseMimes = mLiveCaseMimes;
        }

        boolean screenUnlocked = false;
        boolean liveCaseDetected = false;
        Ndef ndef = Ndef.get(tag);
        if (!provisioningOnly &&
                mScreenStateHelper.checkScreenState() == ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
            screenUnlocked = handleNfcUnlock(tag);

            if (ndef != null) {
                message = ndef.getCachedNdefMessage();
                if (message != null) {
                    String ndefMimeType = message.getRecords()[0].toMimeType();
                    if (liveCaseMimes != null &&
                            Arrays.asList(liveCaseMimes).contains(ndefMimeType)) {
                        liveCaseDetected = true;
                    }
                }
            }

            if (!screenUnlocked && !liveCaseDetected)
                return DISPATCH_FAIL;
        }

        if (ndef != null) {
            message = ndef.getCachedNdefMessage();
        } else {
            NfcBarcode nfcBarcode = NfcBarcode.get(tag);
            if (nfcBarcode != null && nfcBarcode.getType() == NfcBarcode.TYPE_KOVIO) {
                message = decodeNfcBarcodeUri(nfcBarcode);
            }
        }

        if (DBG) Log.d(TAG, "dispatch tag: " + tag.toString() + " message: " + message);

        DispatchInfo dispatch = new DispatchInfo(mContext, tag, message);

        resumeAppSwitches();

        if (tryOverrides(dispatch, tag, message, overrideIntent, overrideFilters,
                overrideTechLists)) {
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
        }

        if (tryPeripheralHandover(message)) {
            if (DBG) Log.i(TAG, "matched BT HANDOVER");
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
        }

        if (NfcWifiProtectedSetup.tryNfcWifiSetup(ndef, mContext)) {
            if (DBG) Log.i(TAG, "matched NFC WPS TOKEN");
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
        }

        if (provisioningOnly) {
            if (message == null) {
                // We only allow NDEF-message dispatch in provisioning mode
                return DISPATCH_FAIL;
            }
            // Restrict to mime-types in whitelist.
            String ndefMimeType = message.getRecords()[0].toMimeType();
            if (provisioningMimes == null ||
                    !(Arrays.asList(provisioningMimes).contains(ndefMimeType))) {
                Log.e(TAG, "Dropping NFC intent in provisioning mode.");
                return DISPATCH_FAIL;
            }
        }

        if (tryNdef(dispatch, message)) {
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
        }

        if (screenUnlocked) {
            // We only allow NDEF-based mimeType matching in case of an unlock
            return DISPATCH_UNLOCK;
        }

        // Only allow NDEF-based mimeType matching for unlock tags
        if (tryTech(dispatch, tag)) {
            return DISPATCH_SUCCESS;
        }

        dispatch.setTagIntent();
        if (dispatch.tryStartActivity()) {
            if (DBG) Log.i(TAG, "matched TAG");
            return DISPATCH_SUCCESS;
        }

        if (DBG) Log.i(TAG, "no match");
        return DISPATCH_FAIL;
    }

    private boolean handleNfcUnlock(Tag tag) {
        return mNfcUnlockManager.tryUnlock(tag);
    }

    /**
     * Checks for the presence of a URL stored in a tag with tech NfcBarcode.
     * If found, decodes URL and returns NdefMessage message containing an
     * NdefRecord containing the decoded URL. If not found, returns null.
     *
     * URLs are decoded as follows:
     *
     * Ignore first byte (which is 0x80 ORd with a manufacturer ID, corresponding
     * to ISO/IEC 7816-6).
     * The second byte describes the payload data format. There are four defined data
     * format values that identify URL data. Depending on the data format value, the
     * associated prefix is appended to the URL data:
     *
     * 0x01: URL with "http://www." prefix
     * 0x02: URL with "https://www." prefix
     * 0x03: URL with "http://" prefix
     * 0x04: URL with "https://" prefix
     *
     * Other data format values do not identify URL data and are not handled by this function.
     * URL payload is encoded in US-ASCII, following the limitations defined in RFC3987.
     * see http://www.ietf.org/rfc/rfc3987.txt
     *
     * The final two bytes of a tag with tech NfcBarcode are always reserved for CRC data,
     * and are therefore not part of the payload. They are ignored in the decoding of a URL.
     *
     * The default assumption is that the URL occupies the entire payload of the NfcBarcode
     * ID and all bytes of the NfcBarcode payload are decoded until the CRC (final two bytes)
     * is reached. However, the OPTIONAL early terminator byte 0xfe can be used to signal
     * an early end of the URL. Once this function reaches an early terminator byte 0xfe,
     * URL decoding stops and the NdefMessage is created and returned. Any payload data after
     * the first early terminator byte is ignored for the purposes of URL decoding.
     */
    private NdefMessage decodeNfcBarcodeUri(NfcBarcode nfcBarcode) {
        final byte URI_PREFIX_HTTP_WWW  = (byte) 0x01; // "http://www."
        final byte URI_PREFIX_HTTPS_WWW = (byte) 0x02; // "https://www."
        final byte URI_PREFIX_HTTP      = (byte) 0x03; // "http://"
        final byte URI_PREFIX_HTTPS     = (byte) 0x04; // "https://"

        NdefMessage message = null;
        byte[] tagId = nfcBarcode.getTag().getId();
        // All tags of NfcBarcode technology and Kovio type have lengths of a multiple of 16 bytes
        if (tagId.length >= 4
                && (tagId[1] == URI_PREFIX_HTTP_WWW || tagId[1] == URI_PREFIX_HTTPS_WWW
                    || tagId[1] == URI_PREFIX_HTTP || tagId[1] == URI_PREFIX_HTTPS)) {
            // Look for optional URI terminator (0xfe), used to indicate the end of a URI prior to
            // the end of the full NfcBarcode payload. No terminator means that the URI occupies the
            // entire length of the payload field. Exclude checking the CRC in the final two bytes
            // of the NfcBarcode tagId.
            int end = 2;
            for (; end < tagId.length - 2; end++) {
                if (tagId[end] == (byte) 0xfe) {
                    break;
                }
            }
            byte[] payload = new byte[end - 1]; // Skip also first byte (manufacturer ID)
            System.arraycopy(tagId, 1, payload, 0, payload.length);
            NdefRecord uriRecord = new NdefRecord(
                    NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, tagId, payload);
            message = new NdefMessage(uriRecord);
        }
        return message;
    }

    boolean tryOverrides(DispatchInfo dispatch, Tag tag, NdefMessage message, PendingIntent overrideIntent,
            IntentFilter[] overrideFilters, String[][] overrideTechLists) {
        if (overrideIntent == null) {
            return false;
        }
        Intent intent;

        // NDEF
        if (message != null) {
            intent = dispatch.setNdefIntent();
            if (intent != null &&
                    isFilterMatch(intent, overrideFilters, overrideTechLists != null)) {
                try {
                    overrideIntent.send(mContext, Activity.RESULT_OK, intent);
                    if (DBG) Log.i(TAG, "matched NDEF override");
                    return true;
                } catch (CanceledException e) {
                    return false;
                }
            }
        }

        // TECH
        intent = dispatch.setTechIntent();
        if (isTechMatch(tag, overrideTechLists)) {
            try {
                overrideIntent.send(mContext, Activity.RESULT_OK, intent);
                if (DBG) Log.i(TAG, "matched TECH override");
                return true;
            } catch (CanceledException e) {
                return false;
            }
        }

        // TAG
        intent = dispatch.setTagIntent();
        if (isFilterMatch(intent, overrideFilters, overrideTechLists != null)) {
            try {
                overrideIntent.send(mContext, Activity.RESULT_OK, intent);
                if (DBG) Log.i(TAG, "matched TAG override");
                return true;
            } catch (CanceledException e) {
                return false;
            }
        }
        return false;
    }

    boolean isFilterMatch(Intent intent, IntentFilter[] filters, boolean hasTechFilter) {
        if (filters != null) {
            for (IntentFilter filter : filters) {
                if (filter.match(mContentResolver, intent, false, TAG) >= 0) {
                    return true;
                }
            }
        } else if (!hasTechFilter) {
            return true;  // always match if both filters and techlists are null
        }
        return false;
    }

    boolean isTechMatch(Tag tag, String[][] techLists) {
        if (techLists == null) {
            return false;
        }

        String[] tagTechs = tag.getTechList();
        Arrays.sort(tagTechs);
        for (String[] filterTechs : techLists) {
            if (filterMatch(tagTechs, filterTechs)) {
                return true;
            }
        }
        return false;
    }

    boolean tryNdef(DispatchInfo dispatch, NdefMessage message) {
        if (message == null) {
            return false;
        }
        Intent intent = dispatch.setNdefIntent();

        // Bail out if the intent does not contain filterable NDEF data
        if (intent == null) return false;

        // Try to start AAR activity with matching filter
        List<String> aarPackages = extractAarPackages(message);
        for (String pkg : aarPackages) {
            dispatch.intent.setPackage(pkg);
            if (dispatch.tryStartActivity()) {
                if (DBG) Log.i(TAG, "matched AAR to NDEF");
                return true;
            }
        }

        // Try to perform regular launch of the first AAR
        if (aarPackages.size() > 0) {
            String firstPackage = aarPackages.get(0);
            PackageManager pm;
            try {
                UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
                pm = mContext.createPackageContextAsUser("android", 0,
                        currentUser).getPackageManager();
            } catch (NameNotFoundException e) {
                Log.e(TAG, "Could not create user package context");
                return false;
            }
            Intent appLaunchIntent = pm.getLaunchIntentForPackage(firstPackage);
            if (appLaunchIntent != null) {
                ResolveInfo ri = pm.resolveActivity(appLaunchIntent, 0);
                if (ri != null && ri.activityInfo != null && ri.activityInfo.exported &&
                        dispatch.tryStartActivity(appLaunchIntent)) {
                    if (DBG) Log.i(TAG, "matched AAR to application launch");
                    return true;
                }
            }
            // Find the package in Market:
            Intent marketIntent = getAppSearchIntent(firstPackage);
            if (marketIntent != null && dispatch.tryStartActivity(marketIntent)) {
                if (DBG) Log.i(TAG, "matched AAR to market launch");
                return true;
            }
        }

        // regular launch
        dispatch.intent.setPackage(null);

        if (dispatch.isWebIntent() && dispatch.hasIntentReceiver()) {
            if (DBG) Log.i(TAG, "matched Web link - prompting user");
            showWebLinkConfirmation(dispatch);
            return true;
        }

        try {
            UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
            PackageManager pm = mContext.createPackageContextAsUser("android", 0,
                        currentUser).getPackageManager();
            ResolveInfo ri = pm.resolveActivity(intent, 0);

            if (ri != null && ri.activityInfo != null && ri.activityInfo.exported && dispatch.tryStartActivity()) {
                if (DBG) Log.i(TAG, "matched NDEF");
                return true;
            }
        } catch (NameNotFoundException ignore) {
            Log.e(TAG, "Could not create user package context");
        }

        return false;
    }

    static List<String> extractAarPackages(NdefMessage message) {
        List<String> aarPackages = new LinkedList<String>();
        for (NdefRecord record : message.getRecords()) {
            String pkg = checkForAar(record);
            if (pkg != null) {
                aarPackages.add(pkg);
            }
        }
        return aarPackages;
    }

    boolean tryTech(DispatchInfo dispatch, Tag tag) {
        dispatch.setTechIntent();

        String[] tagTechs = tag.getTechList();
        Arrays.sort(tagTechs);

        // Standard tech dispatch path
        ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
        List<ComponentInfo> registered = mTechListFilters.getComponents();

        PackageManager pm;
        try {
            UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
            pm = mContext.createPackageContextAsUser("android", 0,
                    currentUser).getPackageManager();
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Could not create user package context");
            return false;
        }
        // Check each registered activity to see if it matches
        for (ComponentInfo info : registered) {
            // Don't allow wild card matching
            if (filterMatch(tagTechs, info.techs) &&
                    isComponentEnabled(pm, info.resolveInfo)) {
                // Add the activity as a match if it's not already in the list
                // Check if exported flag is not explicitly set to false to prevent
                // SecurityExceptions.
                if (!matches.contains(info.resolveInfo) && info.resolveInfo.activityInfo.exported) {
                    matches.add(info.resolveInfo);
                }
            }
        }

        if (matches.size() == 1) {
            // Single match, launch directly
            ResolveInfo info = matches.get(0);
            dispatch.intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
            if (dispatch.tryStartActivity()) {
                if (DBG) Log.i(TAG, "matched single TECH");
                return true;
            }
            dispatch.intent.setComponent(null);
        } else if (matches.size() > 1) {
            // Multiple matches, show a custom activity chooser dialog
            Intent intent = new Intent(mContext, TechListChooserActivity.class);
            intent.putExtra(Intent.EXTRA_INTENT, dispatch.intent);
            intent.putParcelableArrayListExtra(TechListChooserActivity.EXTRA_RESOLVE_INFOS,
                    matches);
            if (dispatch.tryStartActivity(intent)) {
                if (DBG) Log.i(TAG, "matched multiple TECH");
                return true;
            }
        }
        return false;
    }

    public boolean tryPeripheralHandover(NdefMessage m) {
        if (m == null || !mDeviceSupportsBluetooth) return false;

        if (DBG) Log.d(TAG, "tryHandover(): " + m.toString());

        HandoverDataParser.BluetoothHandoverData handover = mHandoverDataParser.parseBluetooth(m);
        if (handover == null || !handover.valid) return false;
        if (UserManager.get(mContext).hasUserRestriction(
                UserManager.DISALLOW_CONFIG_BLUETOOTH,
                // hasUserRestriction does not support UserHandle.CURRENT
                UserHandle.of(ActivityManager.getCurrentUser()))) {
            return false;
        }

        Intent intent = new Intent(mContext, PeripheralHandoverService.class);
        intent.putExtra(PeripheralHandoverService.EXTRA_PERIPHERAL_DEVICE, handover.device);
        intent.putExtra(PeripheralHandoverService.EXTRA_PERIPHERAL_NAME, handover.name);
        intent.putExtra(PeripheralHandoverService.EXTRA_PERIPHERAL_TRANSPORT, handover.transport);
        if (handover.oobData != null) {
            intent.putExtra(PeripheralHandoverService.EXTRA_PERIPHERAL_OOB_DATA, handover.oobData);
        }
        if (handover.uuids != null) {
            intent.putExtra(PeripheralHandoverService.EXTRA_PERIPHERAL_UUIDS, handover.uuids);
        }
        if (handover.btClass != null) {
            intent.putExtra(PeripheralHandoverService.EXTRA_PERIPHERAL_CLASS, handover.btClass);
        }
        intent.putExtra(PeripheralHandoverService.EXTRA_BT_ENABLED, mBluetoothEnabledByNfc.get());
        intent.putExtra(PeripheralHandoverService.EXTRA_CLIENT, mMessenger);
        mContext.startServiceAsUser(intent, UserHandle.CURRENT);

        return true;
    }


    /**
     * Tells the ActivityManager to resume allowing app switches.
     *
     * If the current app called stopAppSwitches() then our startActivity() can
     * be delayed for several seconds. This happens with the default home
     * screen.  As a system service we can override this behavior with
     * resumeAppSwitches().
    */
    void resumeAppSwitches() {
        try {
            mIActivityManager.resumeAppSwitches();
        } catch (RemoteException e) { }
    }

    /** Returns true if the tech list filter matches the techs on the tag */
    boolean filterMatch(String[] tagTechs, String[] filterTechs) {
        if (filterTechs == null || filterTechs.length == 0) return false;

        for (String tech : filterTechs) {
            if (Arrays.binarySearch(tagTechs, tech) < 0) {
                return false;
            }
        }
        return true;
    }

    static String checkForAar(NdefRecord record) {
        if (record.getTnf() == NdefRecord.TNF_EXTERNAL_TYPE &&
                Arrays.equals(record.getType(), NdefRecord.RTD_ANDROID_APP)) {
            return new String(record.getPayload(), StandardCharsets.US_ASCII);
        }
        return null;
    }

    /**
     * Returns an intent that can be used to find an application not currently
     * installed on the device.
     */
    static Intent getAppSearchIntent(String pkg) {
        Intent market = new Intent(Intent.ACTION_VIEW);
        market.setData(Uri.parse("market://details?id=" + pkg));
        return market;
    }

    static boolean isComponentEnabled(PackageManager pm, ResolveInfo info) {
        boolean enabled = false;
        ComponentName compname = new ComponentName(
                info.activityInfo.packageName, info.activityInfo.name);
        try {
            // Note that getActivityInfo() will internally call
            // isEnabledLP() to determine whether the component
            // enabled. If it's not, null is returned.
            if (pm.getActivityInfo(compname,0) != null) {
                enabled = true;
            }
        } catch (PackageManager.NameNotFoundException e) {
            enabled = false;
        }
        if (!enabled) {
            Log.d(TAG, "Component not enabled: " + compname);
        }
        return enabled;
    }

    void showWebLinkConfirmation(DispatchInfo dispatch) {
        if (!mContext.getResources().getBoolean(R.bool.enable_nfc_url_open_dialog)) {
            dispatch.tryStartActivity();
            return;
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(
                mContext.getApplicationContext(),
                android.R.style.Theme_DeviceDefault_Light_Dialog_Alert);
        builder.setTitle(R.string.title_confirm_url_open);
        LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(R.layout.url_open_confirmation, null);
        if (view != null) {
            TextView url = view.findViewById(R.id.url_open_confirmation_link);
            if (url != null) {
                url.setText(dispatch.getUri());
            }
            builder.setView(view);
        }
        builder.setNegativeButton(R.string.cancel, (dialog, which) -> {});
        builder.setPositiveButton(R.string.action_confirm_url_open, (dialog, which) -> {
            dispatch.tryStartActivity();
        });
        AlertDialog dialog = builder.create();
        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        dialog.show();
    }

    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (this) {
            pw.println("mOverrideIntent=" + mOverrideIntent);
            pw.println("mOverrideFilters=" + mOverrideFilters);
            pw.println("mOverrideTechLists=" + mOverrideTechLists);
        }
    }

    private class MessageHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            if (DBG) Log.d(TAG, "handleMessage: msg=" + msg);

            switch (msg.what) {
                case PeripheralHandoverService.MSG_HEADSET_CONNECTED:
                case PeripheralHandoverService.MSG_HEADSET_NOT_CONNECTED:
                    mBluetoothEnabledByNfc.set(msg.arg1 != 0);
                    break;
                default:
                    break;
            }
        }
    }

    final BroadcastReceiver mBluetoothStatusReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                handleBluetoothStateChanged(intent);
            }
        }

        private void handleBluetoothStateChanged(Intent intent) {
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
                    BluetoothAdapter.ERROR);
            if (state == BluetoothAdapter.STATE_OFF) {
                mBluetoothEnabledByNfc.set(false);
            }
        }
    };
}
