diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/java/android/server/BluetoothDeviceService.java | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/java/android/server/BluetoothDeviceService.java')
-rw-r--r-- | core/java/android/server/BluetoothDeviceService.java | 1107 |
1 files changed, 0 insertions, 1107 deletions
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java deleted file mode 100644 index fa53a60..0000000 --- a/core/java/android/server/BluetoothDeviceService.java +++ /dev/null @@ -1,1107 +0,0 @@ -/* - * 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.BluetoothError; -import android.bluetooth.BluetoothHeadset; -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.os.Binder; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.os.SystemService; -import android.provider.Settings; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Arrays; -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(); - - /** - * Bring down bluetooth and disable BT in settings. Returns true on success. - */ - public boolean disable() { - return disable(true); - } - - /** - * Bring down bluetooth. Returns true on success. - * - * @param saveSetting If true, disable BT in settings - * - */ - public synchronized boolean disable(boolean saveSetting) { - 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; - if (saveSetting) { - persistBluetoothOnSetting(false); - } - mIsDiscovering = false; - intent = new Intent(BluetoothIntent.DISABLED_ACTION); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - return true; - } - - /** - * Bring up bluetooth, asynchronously, and enable BT in settings. - * This turns on/off the underlying hardware. - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. - */ - public boolean enable(IBluetoothDeviceCallback callback) { - return enable(callback, true); - } - - /** - * Enable this Bluetooth device, asynchronously. - * This turns on/off the underlying hardware. - * - * @param saveSetting If true, enable BT in settings - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. - */ - public synchronized boolean enable(IBluetoothDeviceCallback callback, - boolean saveSetting) { - 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, saveSetting); - 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; - private final boolean mSaveSetting; - public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) { - mEnableCallback = callback; - mSaveSetting = saveSetting; - } - 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; - if (mSaveSetting) { - 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>(); - private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>(); - // List of all the vendor_id prefix of Bluetooth addresses for which - // auto pairing is not attempted - private final ArrayList<String> mAutoPairingBlacklisted = - new ArrayList<String>(Arrays.asList( - "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS - "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS - "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57"// Murata for Prius 2007 - )); - - 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, but reason code is " + - "invalid. Overriding reason code with BOND_RESULT_REMOVED"); - reason = BluetoothDevice.UNBOND_REASON_REMOVED; - } - intent.putExtra(BluetoothIntent.REASON, reason); - mState.remove(address); - } else { - mState.put(address, state); - } - - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - } - - public boolean isAutoPairingBlacklisted(String address) { - for (String blacklistAddress : mAutoPairingBlacklisted) { - if (address.startsWith(blacklistAddress)) return true; - } - return false; - } - - 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 void addAutoPairingFailure(String address) { - if (!mAutoPairingFailures.contains(address)) { - mAutoPairingFailures.add(address); - } - } - - public synchronized boolean isAutoPairingAttemptsInProgress(String address) { - return getAttempt(address) != 0; - } - - public synchronized void clearPinAttempts(String address) { - mPinAttempt.remove(address); - } - - public synchronized boolean hasAutoPairingFailed(String address) { - return mAutoPairingFailures.contains(address); - } - - 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); - int newAttempt; - if (attempt == null) { - newAttempt = 1; - } else { - newAttempt = attempt.intValue() + 1; - } - mPinAttempt.put(address, new Integer(newAttempt)); - } - - } - 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(); - - // 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) { - 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, false); - } else { - disable(false); - } - } - } - } - }; - - 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); - } -} |