/*
 * Copyright (C) 2008 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.
 */

/**
 * TODO: Move this to
 * java/services/com/android/server/BluetoothDeviceService.java
 * and make the contructor package private again.
 *
 * @hide
 */

package android.server;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;  // just for dump()
import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothIntent;
import android.bluetooth.IBluetoothDevice;
import android.bluetooth.IBluetoothDeviceCallback;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.SystemService;

import java.io.IOException;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class BluetoothDeviceService extends IBluetoothDevice.Stub {
    private static final String TAG = "BluetoothDeviceService";
    private static final boolean DBG = true;

    private int mNativeData;
    private BluetoothEventLoop mEventLoop;
    private IntentFilter mIntentFilter;
    private boolean mIsAirplaneSensitive;
    private final BondState mBondState = new BondState();  // local cache of bondings
    private volatile boolean mIsEnabled;  // local cache of isEnabledNative()
    private boolean mIsDiscovering;

    private final Context mContext;

    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;

    static {
        classInitNative();
    }
    private native static void classInitNative();

    public BluetoothDeviceService(Context context) {
        mContext = context;
    }

    /** Must be called after construction, and before any other method.
     */
    public synchronized void init() {
        initializeNativeDataNative();
        mIsEnabled = (isEnabledNative() == 1);
        if (mIsEnabled) {
            mBondState.loadBondState();
        }
        mIsDiscovering = false;
        mEventLoop = new BluetoothEventLoop(mContext, this);
        registerForAirplaneMode();
    }
    private native void initializeNativeDataNative();

    @Override
    protected void finalize() throws Throwable {
        if (mIsAirplaneSensitive) {
            mContext.unregisterReceiver(mReceiver);
        }
        try {
            cleanupNativeDataNative();
        } finally {
            super.finalize();
        }
    }
    private native void cleanupNativeDataNative();

    public boolean isEnabled() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mIsEnabled;
    }
    private native int isEnabledNative();

    /**
     * Disable bluetooth. Returns true on success.
     */
    public synchronized boolean disable() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        
        if (mEnableThread != null && mEnableThread.isAlive()) {
            return false;
        }
        if (!mIsEnabled) {
            return true;
        }
        mEventLoop.stop();
        disableNative();

        // mark in progress bondings as cancelled
        for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
            mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
                                    BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
        }
        // update mode
        Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
        intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE);
        mContext.sendBroadcast(intent, BLUETOOTH_PERM);

        mIsEnabled = false;
        persistBluetoothOnSetting(false);
        mIsDiscovering = false;
        intent = new Intent(BluetoothIntent.DISABLED_ACTION);
        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
        return true;
    }

    /**
     * Enable this Bluetooth device, asynchronously.
     * This turns on/off the underlying hardware.
     *
     * @return True on success (so far), guarenteeing the callback with be
     * notified when complete.
     */
    public synchronized boolean enable(IBluetoothDeviceCallback callback) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");

        // Airplane mode can prevent Bluetooth radio from being turned on.
        if (mIsAirplaneSensitive && isAirplaneModeOn()) {
            return false;
        }
        if (mIsEnabled) {
            return false;
        }
        if (mEnableThread != null && mEnableThread.isAlive()) {
            return false;
        }
        mEnableThread = new EnableThread(callback);
        mEnableThread.start();
        return true;
    }

    private static final int REGISTER_SDP_RECORDS = 1;
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case REGISTER_SDP_RECORDS:
                //TODO: Don't assume HSP/HFP is running, don't use sdptool,
                if (isEnabled()) {
                    SystemService.start("hsag");
                    SystemService.start("hfag");
                }
            }
        }
    };

    private EnableThread mEnableThread;

    private class EnableThread extends Thread {
        private final IBluetoothDeviceCallback mEnableCallback;
        public EnableThread(IBluetoothDeviceCallback callback) {
            mEnableCallback = callback;
        }
        public void run() {
            boolean res = (enableNative() == 0);
            if (res) {
                mEventLoop.start();
            }

            if (mEnableCallback != null) {
                try {
                    mEnableCallback.onEnableResult(res ?
                                                   BluetoothDevice.RESULT_SUCCESS :
                                                   BluetoothDevice.RESULT_FAILURE);
                } catch (RemoteException e) {}
            }

            if (res) {
                mIsEnabled = true;
                persistBluetoothOnSetting(true);
                mIsDiscovering = false;
                Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
                mBondState.loadBondState();
                mContext.sendBroadcast(intent, BLUETOOTH_PERM);
                mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000);

                // Update mode
                mEventLoop.onModeChanged(getModeNative());
            }
            mEnableThread = null;
        }
    }

    private void persistBluetoothOnSetting(boolean bluetoothOn) {
        long origCallerIdentityToken = Binder.clearCallingIdentity();
        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
                bluetoothOn ? 1 : 0);
        Binder.restoreCallingIdentity(origCallerIdentityToken);        
    }
    
    private native int enableNative();
    private native int disableNative();

    /* package */ BondState getBondState() {
        return mBondState;
    }

    /** local cache of bonding state.
    /* we keep our own state to track the intermediate state BONDING, which
    /* bluez does not track.
     * All addreses must be passed in upper case.
     */
    public class BondState {
        private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
        private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();

        public synchronized void loadBondState() {
            if (!mIsEnabled) {
                return;
            }
            String[] bonds = listBondingsNative();
            if (bonds == null) {
                return;
            }
            mState.clear();
            if (DBG) log("found " + bonds.length + " bonded devices");
            for (String address : bonds) {
                mState.put(address.toUpperCase(), BluetoothDevice.BOND_BONDED);
            }
        }

        public synchronized void setBondState(String address, int state) {
            setBondState(address, state, 0);
        }

        /** reason is ignored unless state == BOND_NOT_BONDED */
        public synchronized void setBondState(String address, int state, int reason) {
            int oldState = getBondState(address);
            if (oldState == state) {
                return;
            }
            if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" +
                         reason + ")");
            Intent intent = new Intent(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
            intent.putExtra(BluetoothIntent.ADDRESS, address);
            intent.putExtra(BluetoothIntent.BOND_STATE, state);
            intent.putExtra(BluetoothIntent.BOND_PREVIOUS_STATE, oldState);
            if (state == BluetoothDevice.BOND_NOT_BONDED) {
                if (reason <= 0) {
                    Log.w(TAG, "setBondState() called to unbond device with invalid reason code " +
                          "Setting reason = BOND_RESULT_REMOVED");
                    reason = BluetoothDevice.UNBOND_REASON_REMOVED;
                }
                intent.putExtra(BluetoothIntent.REASON, reason);
                mState.remove(address);
            } else {
                mState.put(address, state);
            }
            if (state == BluetoothDevice.BOND_BONDING) {
                mPinAttempt.put(address, Integer.valueOf(0));
            } else {
                mPinAttempt.remove(address);
            }
            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
        }

        public synchronized int getBondState(String address) {
            Integer state = mState.get(address);
            if (state == null) {
                return BluetoothDevice.BOND_NOT_BONDED;
            }
            return state.intValue();
        }

        private synchronized String[] listInState(int state) {
            ArrayList<String> result = new ArrayList<String>(mState.size());
            for (Map.Entry<String, Integer> e : mState.entrySet()) {
                if (e.getValue().intValue() == state) {
                    result.add(e.getKey());
                }
            }
            return result.toArray(new String[result.size()]);
        }

        public synchronized int getAttempt(String address) {
            Integer attempt = mPinAttempt.get(address);
            if (attempt == null) {
                return 0;
            }
            return attempt.intValue();
        }

        public synchronized void attempt(String address) {
            Integer attempt = mPinAttempt.get(address);
            if (attempt == null) {
                return;
            }
            mPinAttempt.put(address, new Integer(attempt.intValue() + 1));
        }

    }
    private native String[] listBondingsNative();

    private static String toBondStateString(int bondState) {
        switch (bondState) {
        case BluetoothDevice.BOND_NOT_BONDED:
            return "not bonded";
        case BluetoothDevice.BOND_BONDING:
            return "bonding";
        case BluetoothDevice.BOND_BONDED:
            return "bonded";
        default:
            return "??????";
        }
    }

    public synchronized String getAddress() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getAddressNative();
    }
    private native String getAddressNative();

    public synchronized String getName() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getNameNative();
    }
    private native String getNameNative();

    public synchronized boolean setName(String name) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (name == null) {
            return false;
        }
        // hcid handles persistance of the bluetooth name
        return setNameNative(name);
    }
    private native boolean setNameNative(String name);

    /**
     * Returns the user-friendly name of a remote device.  This value is
     * retrned from our local cache, which is updated during device discovery.
     * Do not expect to retrieve the updated remote name immediately after
     * changing the name on the remote device.
     *
     * @param address Bluetooth address of remote device.
     *
     * @return The user-friendly name of the specified remote device.
     */
    public synchronized String getRemoteName(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteNameNative(address);
    }
    private native String getRemoteNameNative(String address);

    /* pacakge */ native String getAdapterPathNative();

    public synchronized boolean startDiscovery(boolean resolveNames) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return startDiscoveryNative(resolveNames);
    }
    private native boolean startDiscoveryNative(boolean resolveNames);

    public synchronized boolean cancelDiscovery() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return cancelDiscoveryNative();
    }
    private native boolean cancelDiscoveryNative();

    public synchronized boolean isDiscovering() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mIsDiscovering;
    }

    /* package */ void setIsDiscovering(boolean isDiscovering) {
        mIsDiscovering = isDiscovering;
    }

    public synchronized boolean startPeriodicDiscovery() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return startPeriodicDiscoveryNative();
    }
    private native boolean startPeriodicDiscoveryNative();

    public synchronized boolean stopPeriodicDiscovery() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return stopPeriodicDiscoveryNative();
    }
    private native boolean stopPeriodicDiscoveryNative();

    public synchronized boolean isPeriodicDiscovery() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return isPeriodicDiscoveryNative();
    }
    private native boolean isPeriodicDiscoveryNative();

    /**
     * Set the discoverability window for the device.  A timeout of zero
     * makes the device permanently discoverable (if the device is
     * discoverable).  Setting the timeout to a nonzero value does not make
     * a device discoverable; you need to call setMode() to make the device
     * explicitly discoverable.
     *
     * @param timeout_s The discoverable timeout in seconds.
     */
    public synchronized boolean setDiscoverableTimeout(int timeout) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return setDiscoverableTimeoutNative(timeout);
    }
    private native boolean setDiscoverableTimeoutNative(int timeout_s);

    /**
     * Get the discoverability window for the device.  A timeout of zero
     * means that the device is permanently discoverable (if the device is
     * in the discoverable mode).
     *
     * @return The discoverability window of the device, in seconds.  A negative
     *         value indicates an error.
     */
    public synchronized int getDiscoverableTimeout() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getDiscoverableTimeoutNative();
    }
    private native int getDiscoverableTimeoutNative();

    public synchronized boolean isAclConnected(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        return isConnectedNative(address);
    }
    private native boolean isConnectedNative(String address);

    public synchronized int getScanMode() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return bluezStringToScanMode(getModeNative());
    }
    private native String getModeNative();

    public synchronized boolean setScanMode(int mode) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        String bluezMode = scanModeToBluezString(mode);
        if (bluezMode != null) {
            return setModeNative(bluezMode);
        }
        return false;
    }
    private native boolean setModeNative(String mode);

    public synchronized boolean disconnectRemoteDeviceAcl(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        return disconnectRemoteDeviceNative(address);
    }
    private native boolean disconnectRemoteDeviceNative(String address);

    public synchronized boolean createBond(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        address = address.toUpperCase();
        if (mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) {
            return false;
        }

        if (!createBondingNative(address, 60000 /* 1 minute */)) {
            return false;
        }

        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
        return true;
    }
    private native boolean createBondingNative(String address, int timeout_ms);

    public synchronized boolean cancelBondProcess(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        address = address.toUpperCase();
        if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) {
            return false;
        }

        mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED,
                                BluetoothDevice.UNBOND_REASON_AUTH_CANCELED);
        cancelBondingProcessNative(address);
        return true;
    }
    private native boolean cancelBondingProcessNative(String address);

    public synchronized boolean removeBond(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        return removeBondingNative(address);
    }
    private native boolean removeBondingNative(String address);

    public synchronized String[] listBonds() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mBondState.listInState(BluetoothDevice.BOND_BONDED);
    }

    public synchronized int getBondState(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return BluetoothError.ERROR;
        }
        return mBondState.getBondState(address.toUpperCase());
    }

    public synchronized String[] listAclConnections() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return listConnectionsNative();
    }
    private native String[] listConnectionsNative();

    /**
     * This method lists all remote devices that this adapter is aware of.
     * This is a list not only of all most-recently discovered devices, but of
     * all devices discovered by this adapter up to some point in the past.
     * Note that many of these devices may not be in the neighborhood anymore,
     * and attempting to connect to them will result in an error.
     *
     * @return An array of strings representing the Bluetooth addresses of all
     *         remote devices that this adapter is aware of.
     */
    public synchronized String[] listRemoteDevices() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return listRemoteDevicesNative();
    }
    private native String[] listRemoteDevicesNative();

    /**
     * Returns the version of the Bluetooth chip. This version is compiled from
     * the LMP version. In case of EDR the features attribute must be checked.
     * Example: "Bluetooth 2.0 + EDR".
     *
     * @return a String representation of the this Adapter's underlying
     *         Bluetooth-chip version.
     */
    public synchronized String getVersion() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getVersionNative();
    }
    private native String getVersionNative();

    /**
     * Returns the revision of the Bluetooth chip. This is a vendor-specific
     * value and in most cases it represents the firmware version. This might
     * derive from the HCI revision and LMP subversion values or via extra
     * vendord specific commands.
     * In case the revision of a chip is not available. This method should
     * return the LMP subversion value as a string.
     * Example: "HCI 19.2"
     *
     * @return The HCI revision of this adapter.
     */
    public synchronized String getRevision() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getRevisionNative();
    }
    private native String getRevisionNative();

    /**
     * Returns the manufacturer of the Bluetooth chip. If the company id is not
     * known the sting "Company ID %d" where %d should be replaced with the
     * numeric value from the manufacturer field.
     * Example: "Cambridge Silicon Radio"
     *
     * @return Manufacturer name.
     */
    public synchronized String getManufacturer() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getManufacturerNative();
    }
    private native String getManufacturerNative();

    /**
     * Returns the company name from the OUI database of the Bluetooth device
     * address. This function will need a valid and up-to-date oui.txt from
     * the IEEE. This value will be different from the manufacturer string in
     * the most cases.
     * If the oui.txt file is not present or the OUI part of the Bluetooth
     * address is not listed, it should return the string "OUI %s" where %s is
     * the actual OUI.
     *
     * Example: "Apple Computer"
     *
     * @return company name
     */
    public synchronized String getCompany() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getCompanyNative();
    }
    private native String getCompanyNative();

    /**
     * Like getVersion(), but for a remote device.
     *
     * @param address The Bluetooth address of the remote device.
     *
     * @return remote-device Bluetooth version
     *
     * @see #getVersion
     */
    public synchronized String getRemoteVersion(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteVersionNative(address);
    }
    private native String getRemoteVersionNative(String address);

    /**
     * Like getRevision(), but for a remote device.
     *
     * @param address The Bluetooth address of the remote device.
     *
     * @return remote-device HCI revision
     *
     * @see #getRevision
     */
    public synchronized String getRemoteRevision(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteRevisionNative(address);
    }
    private native String getRemoteRevisionNative(String address);

    /**
     * Like getManufacturer(), but for a remote device.
     *
     * @param address The Bluetooth address of the remote device.
     *
     * @return remote-device Bluetooth chip manufacturer
     *
     * @see #getManufacturer
     */
    public synchronized String getRemoteManufacturer(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteManufacturerNative(address);
    }
    private native String getRemoteManufacturerNative(String address);

    /**
     * Like getCompany(), but for a remote device.
     *
     * @param address The Bluetooth address of the remote device.
     *
     * @return remote-device company
     *
     * @see #getCompany
     */
    public synchronized String getRemoteCompany(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteCompanyNative(address);
    }
    private native String getRemoteCompanyNative(String address);

    /**
     * Returns the date and time when the specified remote device has been seen
     * by a discover procedure.
     * Example: "2006-02-08 12:00:00 GMT"
     *
     * @return a String with the timestamp.
     */
    public synchronized String lastSeen(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return lastSeenNative(address);
    }
    private native String lastSeenNative(String address);

    /**
     * Returns the date and time when the specified remote device has last been
     * connected to
     * Example: "2006-02-08 12:00:00 GMT"
     *
     * @return a String with the timestamp.
     */
    public synchronized String lastUsed(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return lastUsedNative(address);
    }
    private native String lastUsedNative(String address);

    /**
     * Gets the remote major, minor, and service classes encoded as a 32-bit
     * integer.
     *
     * Note: this value is retrieved from cache, because we get it during
     *       remote-device discovery.
     *
     * @return 32-bit integer encoding the remote major, minor, and service
     *         classes.
     *
     * @see #getRemoteMajorClass
     * @see #getRemoteMinorClass
     * @see #getRemoteServiceClasses
     */
    public synchronized int getRemoteClass(String address) {
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            return -1;
        }
        return getRemoteClassNative(address);
    }
    private native int getRemoteClassNative(String address);

    /**
     * Gets the remote features encoded as bit mask.
     *
     * Note: This method may be obsoleted soon.
     *
     * @return byte array of features.
     */
    public synchronized byte[] getRemoteFeatures(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteFeaturesNative(address);
    }
    private native byte[] getRemoteFeaturesNative(String address);

    /**
     * This method and {@link #getRemoteServiceRecord} query the SDP service
     * on a remote device.  They do not interpret the data, but simply return
     * it raw to the user.  To read more about SDP service handles and records,
     * consult the Bluetooth core documentation (www.bluetooth.com).
     *
     * @param address Bluetooth address of remote device.
     * @param match a String match to narrow down the service-handle search.
     *        The only supported value currently is "hsp" for the headset
     *        profile.  To retrieve all service handles, simply pass an empty
     *        match string.
     *
     * @return all service handles corresponding to the string match.
     *
     * @see #getRemoteServiceRecord
     */
    public synchronized int[] getRemoteServiceHandles(String address, String match) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        if (match == null) {
            match = "";
        }
        return getRemoteServiceHandlesNative(address, match);
    }
    private native int[] getRemoteServiceHandlesNative(String address, String match);

    /**
     * This method retrieves the service records corresponding to a given
     * service handle (method {@link #getRemoteServiceHandles} retrieves the
     * service handles.)
     *
     * This method and {@link #getRemoteServiceHandles} do not interpret their
     * data, but simply return it raw to the user.  To read more about SDP
     * service handles and records, consult the Bluetooth core documentation
     * (www.bluetooth.com).
     *
     * @param address Bluetooth address of remote device.
     * @param handle Service handle returned by {@link #getRemoteServiceHandles}
     *
     * @return a byte array of all service records corresponding to the
     *         specified service handle.
     *
     * @see #getRemoteServiceHandles
     */
    public synchronized byte[] getRemoteServiceRecord(String address, int handle) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteServiceRecordNative(address, handle);
    }
    private native byte[] getRemoteServiceRecordNative(String address, int handle);

    private static final int MAX_OUTSTANDING_ASYNC = 32;

    // AIDL does not yet support short's
    public synchronized boolean getRemoteServiceChannel(String address, int uuid16,
            IBluetoothDeviceCallback callback) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        HashMap<String, IBluetoothDeviceCallback> callbacks =
            mEventLoop.getRemoteServiceChannelCallbacks();
        if (callbacks.containsKey(address)) {
            Log.w(TAG, "SDP request already in progress for " + address);
            return false;
        }
        // Protect from malicious clients - only allow 32 bonding requests per minute.
        if (callbacks.size() > MAX_OUTSTANDING_ASYNC) {
            Log.w(TAG, "Too many outstanding SDP requests, dropping request for " + address);
            return false;
        }
        callbacks.put(address, callback);

        if (!getRemoteServiceChannelNative(address, (short)uuid16)) {
            callbacks.remove(address);
            return false;
        }
        return true;
    }
    private native boolean getRemoteServiceChannelNative(String address, short uuid16);

    public synchronized boolean setPin(String address, byte[] pin) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (pin == null || pin.length <= 0 || pin.length > 16 ||
            !BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        address = address.toUpperCase();
        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
        if (data == null) {
            Log.w(TAG, "setPin(" + address + ") called but no native data available, " +
                  "ignoring. Maybe the PasskeyAgent Request was cancelled by the remote device" +
                  " or by bluez.\n");
            return false;
        }
        // bluez API wants pin as a string
        String pinString;
        try {
            pinString = new String(pin, "UTF8");
        } catch (UnsupportedEncodingException uee) {
            Log.e(TAG, "UTF8 not supported?!?");
            return false;
        }
        return setPinNative(address, pinString, data.intValue());
    }
    private native boolean setPinNative(String address, String pin, int nativeData);

    public synchronized boolean cancelPin(String address) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        address = address.toUpperCase();
        Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address);
        if (data == null) {
            Log.w(TAG, "cancelPin(" + address + ") called but no native data available, " +
                  "ignoring. Maybe the PasskeyAgent Request was already cancelled by the remote " +
                  "or by bluez.\n");
            return false;
        }
        return cancelPinNative(address, data.intValue());
    }
    private native boolean cancelPinNative(String address, int natveiData);

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
                ContentResolver resolver = context.getContentResolver();
                // Query the airplane mode from Settings.System just to make sure that
                // some random app is not sending this intent and disabling bluetooth
                boolean enabled = !isAirplaneModeOn();
                // If bluetooth is currently expected to be on, then enable or disable bluetooth
                if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
                    if (enabled) {
                        enable(null);
                    } else {
                        disable();
                    }
                }
            }
        }
    };

    private void registerForAirplaneMode() {
        String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
                Settings.System.AIRPLANE_MODE_RADIOS);
        mIsAirplaneSensitive = airplaneModeRadios == null
                ? true : airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
        if (mIsAirplaneSensitive) {
            mIntentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
            mContext.registerReceiver(mReceiver, mIntentFilter);
        }
    }

    /* Returns true if airplane mode is currently on */
    private final boolean isAirplaneModeOn() {
        return Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mIsEnabled) {
            pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")");
            pw.println("\nisDiscovering() = " + isDiscovering());

            BluetoothHeadset headset = new BluetoothHeadset(mContext, null);

            String[] addresses = listRemoteDevices();

            pw.println("\n--Known devices--");
            for (String address : addresses) {
                pw.printf("%s %10s (%d) %s\n", address,
                           toBondStateString(mBondState.getBondState(address)),
                           mBondState.getAttempt(address),
                           getRemoteName(address));
            }

            addresses = listAclConnections();
            pw.println("\n--ACL connected devices--");
            for (String address : addresses) {
                pw.println(address);
            }

            // Rather not do this from here, but no-where else and I need this
            // dump
            pw.println("\n--Headset Service--");
            switch (headset.getState()) {
            case BluetoothHeadset.STATE_DISCONNECTED:
                pw.println("getState() = STATE_DISCONNECTED");
                break;
            case BluetoothHeadset.STATE_CONNECTING:
                pw.println("getState() = STATE_CONNECTING");
                break;
            case BluetoothHeadset.STATE_CONNECTED:
                pw.println("getState() = STATE_CONNECTED");
                break;
            case BluetoothHeadset.STATE_ERROR:
                pw.println("getState() = STATE_ERROR");
                break;
            }
            pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress());
            headset.close();

        } else {
            pw.println("\nBluetooth DISABLED");
        }
        pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive);
    }

    /* package */ static int bluezStringToScanMode(String mode) {
        if (mode == null) {
            return BluetoothError.ERROR;
        }
        mode = mode.toLowerCase();
        if (mode.equals("off")) {
            return BluetoothDevice.SCAN_MODE_NONE;
        } else if (mode.equals("connectable")) {
            return BluetoothDevice.SCAN_MODE_CONNECTABLE;
        } else if (mode.equals("discoverable")) {
            return BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
        } else {
            return BluetoothError.ERROR;
        }
    }

    /* package */ static String scanModeToBluezString(int mode) {
        switch (mode) {
        case BluetoothDevice.SCAN_MODE_NONE:
            return "off";
        case BluetoothDevice.SCAN_MODE_CONNECTABLE:
            return "connectable";
        case BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
            return "discoverable";
        }
        return null;
    }

    private static void log(String msg) {
        Log.d(TAG, msg);
    }
}
