FileDocCategorySizeDatePackage
BluetoothDeviceService.javaAPI DocAndroid 1.5 API48568Wed May 06 22:41:56 BST 2009android.server

BluetoothDeviceService

public class BluetoothDeviceService extends IBluetoothDevice.Stub
TODO: Move this to java/services/com/android/server/BluetoothDeviceService.java and make the contructor package private again.
hide

Fields Summary
private static final String
TAG
private static final boolean
DBG
private int
mNativeData
private BluetoothEventLoop
mEventLoop
private android.content.IntentFilter
mIntentFilter
private boolean
mIsAirplaneSensitive
private int
mBluetoothState
private boolean
mRestart
private final BondState
mBondState
private boolean
mIsDiscovering
private final com.android.internal.app.IBatteryStats
mBatteryStats
private final android.content.Context
mContext
private static final String
BLUETOOTH_ADMIN_PERM
private static final String
BLUETOOTH_PERM
private static final int
MESSAGE_REGISTER_SDP_RECORDS
private static final int
MESSAGE_FINISH_DISABLE
private final android.os.Handler
mHandler
private EnableThread
mEnableThread
private static final int
MAX_OUTSTANDING_ASYNC
private final android.content.BroadcastReceiver
mReceiver
Constructors Summary
public BluetoothDeviceService(android.content.Context context)


     
        classInitNative();
    
        mContext = context;

        // Need to do this in place of:
        // mBatteryStats = BatteryStatsService.getService();
        // Since we can not import BatteryStatsService from here. This class really needs to be
        // moved to java/services/com/android/server/
        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
    
Methods Summary
static intbluezStringToScanMode(java.lang.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;
        }
    
public synchronized booleancancelBondProcess(java.lang.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 booleancancelBondingProcessNative(java.lang.String address)

public synchronized booleancancelDiscovery()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return cancelDiscoveryNative();
    
private native booleancancelDiscoveryNative()

public synchronized booleancancelPin(java.lang.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 booleancancelPinNative(java.lang.String address, int natveiData)

private static native voidclassInitNative()

private native voidcleanupNativeDataNative()

public synchronized booleancreateBond(java.lang.String address)

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        address = address.toUpperCase();

        String[] bonding = mBondState.listInState(BluetoothDevice.BOND_BONDING);
        if (bonding.length > 0 && !bonding[0].equals(address)) {
            log("Ignoring createBond(): another device is bonding");
            // a different device is currently bonding, fail
            return false;
        }

        // Check for bond state only if we are not performing auto
        // pairing exponential back-off attempts.
        if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
                mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) {
            log("Ignoring createBond(): this device is already bonding or bonded");
            return false;
        }

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

        mBondState.setBondState(address, BluetoothDevice.BOND_BONDING);
        return true;
    
private native booleancreateBondingNative(java.lang.String address, int timeout_ms)

public booleandisable()
Bring down bluetooth and disable BT in settings. Returns true on success.

        return disable(true);
    
public synchronized booleandisable(boolean saveSetting)
Bring down bluetooth. Returns true on success.

param
saveSetting If true, disable BT in settings

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");

        switch (mBluetoothState) {
        case BluetoothDevice.BLUETOOTH_STATE_OFF:
            return true;
        case BluetoothDevice.BLUETOOTH_STATE_ON:
            break;
        default:
            return false;
        }
        if (mEnableThread != null && mEnableThread.isAlive()) {
            return false;
        }
        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);

        // Allow 3 seconds for profiles to gracefully disconnect
        // TODO: Introduce a callback mechanism so that each profile can notify
        // BluetoothDeviceService when it is done shutting down
        mHandler.sendMessageDelayed(
                mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
        return true;
    
private native intdisableNative()

public synchronized booleandisconnectRemoteDeviceAcl(java.lang.String address)

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        return disconnectRemoteDeviceNative(address);
    
private native booleandisconnectRemoteDeviceNative(java.lang.String address)

protected voiddump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)

        pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n");

        switch(mBluetoothState) {
        case BluetoothDevice.BLUETOOTH_STATE_OFF:
            pw.println("\nBluetooth OFF\n");
            return;
        case BluetoothDevice.BLUETOOTH_STATE_TURNING_ON:
            pw.println("\nBluetooth TURNING ON\n");
            return;
        case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF:
            pw.println("\nBluetooth TURNING OFF\n");
            return;
        case BluetoothDevice.BLUETOOTH_STATE_ON:
            pw.println("\nBluetooth ON\n");
        }

        pw.println("\nLocal address = " + getAddress());
        pw.println("\nLocal name = " + 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();
    
public booleanenable()
Bring up BT and persist BT on in settings

        return enable(true);
    
public synchronized booleanenable(boolean saveSetting)
Enable this Bluetooth device, asynchronously. This turns on/off the underlying hardware.

param
saveSetting If true, persist the new state of BT in settings
return
True on success (so far)

        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 (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_OFF) {
            return false;
        }
        if (mEnableThread != null && mEnableThread.isAlive()) {
            return false;
        }
        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON);
        mEnableThread = new EnableThread(saveSetting);
        mEnableThread.start();
        return true;
    
private native intenableNative()

protected voidfinalize()

        if (mIsAirplaneSensitive) {
            mContext.unregisterReceiver(mReceiver);
        }
        try {
            cleanupNativeDataNative();
        } finally {
            super.finalize();
        }
    
private synchronized voidfinishDisable(boolean saveSetting)

        if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) {
            return;
        }
        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);
        }

        // Remove remoteServiceChannelCallbacks
        HashMap<String, IBluetoothDeviceCallback> callbacksMap =
            mEventLoop.getRemoteServiceChannelCallbacks();

        for (Iterator<String> i = callbacksMap.keySet().iterator(); i.hasNext();) {
            String address = i.next();
            IBluetoothDeviceCallback callback = callbacksMap.get(address);
            try {
                callback.onGetRemoteServiceChannelResult(address, BluetoothError.ERROR_DISABLED);
            } catch (RemoteException e) {}
            i.remove();
        }

        // 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);

        mIsDiscovering = false;

        if (saveSetting) {
            persistBluetoothOnSetting(false);
        }

        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF);

        // Log bluetooth off to battery stats.
        long ident = Binder.clearCallingIdentity();
        try {
            mBatteryStats.noteBluetoothOff();
        } catch (RemoteException e) {
        } finally {
            Binder.restoreCallingIdentity(ident);
        }

        if (mRestart) {
            mRestart = false;
            enable();
        }
    
native java.lang.StringgetAdapterPathNative()

public synchronized java.lang.StringgetAddress()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getAddressNative();
    
private native java.lang.StringgetAddressNative()

public intgetBluetoothState()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mBluetoothState;
    
android.server.BluetoothDeviceService$BondStategetBondState()

        return mBondState;
    
public synchronized intgetBondState(java.lang.String address)

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return BluetoothError.ERROR;
        }
        return mBondState.getBondState(address.toUpperCase());
    
public synchronized java.lang.StringgetCompany()
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

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getCompanyNative();
    
private native java.lang.StringgetCompanyNative()

public synchronized intgetDiscoverableTimeout()
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getDiscoverableTimeoutNative();
    
private native intgetDiscoverableTimeoutNative()

public synchronized java.lang.StringgetManufacturer()
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getManufacturerNative();
    
private native java.lang.StringgetManufacturerNative()

private native java.lang.StringgetModeNative()

public synchronized java.lang.StringgetName()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getNameNative();
    
private native java.lang.StringgetNameNative()

public synchronized intgetRemoteClass(java.lang.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

        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
            return BluetoothClass.ERROR;
        }
        return getRemoteClassNative(address);
    
private native intgetRemoteClassNative(java.lang.String address)

public synchronized java.lang.StringgetRemoteCompany(java.lang.String address)
Like getCompany(), but for a remote device.

param
address The Bluetooth address of the remote device.
return
remote-device company
see
#getCompany

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteCompanyNative(address);
    
private native java.lang.StringgetRemoteCompanyNative(java.lang.String address)

public synchronized byte[]getRemoteFeatures(java.lang.String address)
Gets the remote features encoded as bit mask. Note: This method may be obsoleted soon.

return
byte array of features.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteFeaturesNative(address);
    
private native byte[]getRemoteFeaturesNative(java.lang.String address)

public synchronized java.lang.StringgetRemoteManufacturer(java.lang.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

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteManufacturerNative(address);
    
private native java.lang.StringgetRemoteManufacturerNative(java.lang.String address)

public synchronized java.lang.StringgetRemoteName(java.lang.String address)
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteNameNative(address);
    
private native java.lang.StringgetRemoteNameNative(java.lang.String address)

public synchronized java.lang.StringgetRemoteRevision(java.lang.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

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteRevisionNative(address);
    
private native java.lang.StringgetRemoteRevisionNative(java.lang.String address)

public synchronized booleangetRemoteServiceChannel(java.lang.String address, int uuid16, android.bluetooth.IBluetoothDeviceCallback callback)


    // AIDL does not yet support short's
          
              
        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 booleangetRemoteServiceChannelNative(java.lang.String address, short uuid16)

public synchronized int[]getRemoteServiceHandles(java.lang.String address, java.lang.String match)
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

        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(java.lang.String address, java.lang.String match)

public synchronized byte[]getRemoteServiceRecord(java.lang.String address, int handle)
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

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteServiceRecordNative(address, handle);
    
private native byte[]getRemoteServiceRecordNative(java.lang.String address, int handle)

public synchronized java.lang.StringgetRemoteVersion(java.lang.String address)
Like getVersion(), but for a remote device.

param
address The Bluetooth address of the remote device.
return
remote-device Bluetooth version
see
#getVersion

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return getRemoteVersionNative(address);
    
private native java.lang.StringgetRemoteVersionNative(java.lang.String address)

public synchronized java.lang.StringgetRevision()
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getRevisionNative();
    
private native java.lang.StringgetRevisionNative()

public synchronized intgetScanMode()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return bluezStringToScanMode(getModeNative());
    
public synchronized java.lang.StringgetVersion()
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return getVersionNative();
    
private native java.lang.StringgetVersionNative()

public synchronized voidinit()
Must be called after construction, and before any other method.

        initializeNativeDataNative();

        if (isEnabledNative() == 1) {
            Log.w(TAG, "Bluetooth daemons already running - runtime restart? ");
            disableNative();
        }

        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF);
        mIsDiscovering = false;
        mEventLoop = new BluetoothEventLoop(mContext, this);
        registerForAirplaneMode();
    
private native voidinitializeNativeDataNative()

public synchronized booleanisAclConnected(java.lang.String address)

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        return isConnectedNative(address);
    
private final booleanisAirplaneModeOn()

        return Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.AIRPLANE_MODE_ON, 0) == 1;
    
private native booleanisConnectedNative(java.lang.String address)

public synchronized booleanisDiscovering()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mIsDiscovering;
    
public booleanisEnabled()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mBluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON;
    
private native intisEnabledNative()

public synchronized booleanisPeriodicDiscovery()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return isPeriodicDiscoveryNative();
    
private native booleanisPeriodicDiscoveryNative()

public synchronized java.lang.StringlastSeen(java.lang.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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return lastSeenNative(address);
    
private native java.lang.StringlastSeenNative(java.lang.String address)

public synchronized java.lang.StringlastUsed(java.lang.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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return null;
        }
        return lastUsedNative(address);
    
private native java.lang.StringlastUsedNative(java.lang.String address)

public synchronized java.lang.String[]listAclConnections()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return listConnectionsNative();
    
private native java.lang.String[]listBondingsNative()

public synchronized java.lang.String[]listBonds()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return mBondState.listInState(BluetoothDevice.BOND_BONDED);
    
private native java.lang.String[]listConnectionsNative()

public synchronized java.lang.String[]listRemoteDevices()
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        return listRemoteDevicesNative();
    
private native java.lang.String[]listRemoteDevicesNative()

private static voidlog(java.lang.String msg)

        Log.d(TAG, msg);
    
private voidpersistBluetoothOnSetting(boolean bluetoothOn)

        long origCallerIdentityToken = Binder.clearCallingIdentity();
        Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
                bluetoothOn ? 1 : 0);
        Binder.restoreCallingIdentity(origCallerIdentityToken);
    
private voidregisterForAirplaneMode()


       
        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);
        }
    
public synchronized booleanremoveBond(java.lang.String address)

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        if (!BluetoothDevice.checkBluetoothAddress(address)) {
            return false;
        }
        return removeBondingNative(address);
    
private native booleanremoveBondingNative(java.lang.String address)

synchronized voidrestart()
Forcibly restart Bluetooth if it is on

        if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_ON) {
            return;
        }
        mRestart = true;
        if (!disable(false)) {
            mRestart = false;
        }
    
static java.lang.StringscanModeToBluezString(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 synchronized voidsetBluetoothState(int state)

        if (state == mBluetoothState) {
            return;
        }

        if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state);

        Intent intent = new Intent(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
        intent.putExtra(BluetoothIntent.BLUETOOTH_PREVIOUS_STATE, mBluetoothState);
        intent.putExtra(BluetoothIntent.BLUETOOTH_STATE, state);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);

        mBluetoothState = state;

        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
    
public synchronized booleansetDiscoverableTimeout(int timeout)
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.

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return setDiscoverableTimeoutNative(timeout);
    
private native booleansetDiscoverableTimeoutNative(int timeout_s)

voidsetIsDiscovering(boolean isDiscovering)

        mIsDiscovering = isDiscovering;
    
private native booleansetModeNative(java.lang.String mode)

public synchronized booleansetName(java.lang.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 booleansetNameNative(java.lang.String name)

public synchronized booleansetPin(java.lang.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 booleansetPinNative(java.lang.String address, java.lang.String pin, int nativeData)

public synchronized booleansetScanMode(int mode)

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

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return startDiscoveryNative(resolveNames);
    
private native booleanstartDiscoveryNative(boolean resolveNames)

public synchronized booleanstartPeriodicDiscovery()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return startPeriodicDiscoveryNative();
    
private native booleanstartPeriodicDiscoveryNative()

public synchronized booleanstopPeriodicDiscovery()

        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                "Need BLUETOOTH_ADMIN permission");
        return stopPeriodicDiscoveryNative();
    
private native booleanstopPeriodicDiscoveryNative()

private static java.lang.StringtoBondStateString(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 "??????";
        }