Merge "Add BluetoothDevice#connect and BluetoothDevice#disconnect as System APIs" into stage-aosp-master am: 4a39b54ec1 am: 0db21e73d3
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15936310
Change-Id: Ic42df1b1158199c0f0efaeb166e632d16aa55e0f
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6a57c24..ba7903b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1981,8 +1981,10 @@
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean fetchUuidsWithSdp(int);
method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getSimAccessPermission();
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 77abbe9..e9be0ec 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2005,71 +2005,6 @@
}
/**
- * Connects all enabled and supported bluetooth profiles between the local and remote device.
- * Connection is asynchronous and you should listen to each profile's broadcast intent
- * ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful. For example,
- * to verify a2dp is connected, you would listen for
- * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
- *
- * @param device is the remote device with which to connect these profiles
- * @return true if message sent to try to connect all profiles, false if an error occurred
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- android.Manifest.permission.MODIFY_PHONE_STATE,
- })
- public boolean connectAllEnabledProfiles(@NonNull BluetoothDevice device) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.connectAllEnabledProfiles(device, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
- }
-
- /**
- * Disconnects all enabled and supported bluetooth profiles between the local and remote device.
- * Disconnection is asynchronous and you should listen to each profile's broadcast intent
- * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example,
- * to verify a2dp is disconnected, you would listen for
- * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
- *
- * @param device is the remote device with which to disconnect these profiles
- * @return true if message sent to try to disconnect all profiles, false if an error occurred
- *
- * @hide
- */
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public boolean disconnectAllEnabledProfiles(@NonNull BluetoothDevice device) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- return mService.disconnectAllEnabledProfiles(device, mAttributionSource);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- return false;
- }
-
- /**
* Return true if the multi advertisement is supported by the chipset
*
* @return true if Multiple Advertisement feature is supported
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 71f05f52..6e918bd 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1683,6 +1683,90 @@
return false;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+ BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
+ })
+ public @interface ConnectionReturnValues{}
+
+ /**
+ * Connects all user enabled and supported bluetooth profiles between the local and remote
+ * device. If no profiles are user enabled (e.g. first connection), we connect all supported
+ * profiles. If the device is not already connected, this will page the device before initiating
+ * profile connections. Connection is asynchronous and you should listen to each profile's
+ * broadcast intent ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful.
+ * For example, to verify a2dp is connected, you would listen for
+ * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
+ *
+ * @return whether the messages were successfully sent to try to connect all profiles
+ * @throws IllegalArgumentException if the device address is invalid
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
+ public @ConnectionReturnValues int connect() {
+ if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+
+ try {
+ if (sService == null) {
+ Log.e(TAG, "BT not enabled. Cannot connect to remote device.");
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ return sService.connectAllEnabledProfiles(this, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Disconnects all connected bluetooth profiles between the local and remote device.
+ * Disconnection is asynchronous and you should listen to each profile's broadcast intent
+ * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example,
+ * to verify a2dp is disconnected, you would listen for
+ * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
+ *
+ * @return whether the messages were successfully sent to try to disconnect all profiles
+ * @throws IllegalArgumentException if the device address is invalid
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @ConnectionReturnValues int disconnect() {
+ if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+
+ try {
+ if (sService == null) {
+ Log.e(TAG, "BT not enabled. Cannot disconnect from remote device.");
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ return sService.disconnectAllEnabledProfiles(this, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Returns whether there is an open connection to this device.
*
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index 31bb0f6..3e46c49 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -21,7 +21,7 @@
/**
* A class with constants representing possible return values for Bluetooth APIs. General return
* values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999.
- * API-specific return values start at 1000. The exception to this is the "other" error code which
+ * API-specific return values start at 1000. The exception to this is the "UNKNOWN" error code which
* occupies the max integer value.
*/
public final class BluetoothStatusCodes {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 5ecff44..7ce9b51 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -273,7 +273,7 @@
public void disconnect() {
synchronized (mProfileLock) {
- mLocalAdapter.disconnectAllEnabledProfiles(mDevice);
+ mDevice.disconnect();
}
// Disconnect PBAP server in case its connected
// This is to ensure all the profiles are disconnected as some CK/Hs do not
@@ -314,7 +314,7 @@
}
mConnectAttempted = SystemClock.elapsedRealtime();
- connectAllEnabledProfiles();
+ connectDevice();
}
public long getHiSyncId() {
@@ -371,7 +371,7 @@
connect();
}
- private void connectAllEnabledProfiles() {
+ private void connectDevice() {
synchronized (mProfileLock) {
// Try to initialize the profiles if they were not.
if (mProfiles.isEmpty()) {
@@ -386,7 +386,7 @@
return;
}
- mLocalAdapter.connectAllEnabledProfiles(mDevice);
+ mDevice.connect();
}
}
@@ -769,8 +769,8 @@
* Otherwise, allow the connect on UUID change.
*/
if ((mConnectAttempted + timeout) > SystemClock.elapsedRealtime()) {
- Log.d(TAG, "onUuidChanged: triggering connectAllEnabledProfiles");
- connectAllEnabledProfiles();
+ Log.d(TAG, "onUuidChanged: triggering connectDevice");
+ connectDevice();
}
dispatchAttributesChanged();