Merge "Add BluetoothDevice#connect and BluetoothDevice#disconnect as System APIs" into stage-aosp-master

This commit is contained in:
Rahul Sabnis
2021-09-30 18:04:55 +00:00
committed by Android (Google) Code Review
5 changed files with 93 additions and 72 deletions

View File

@@ -1981,8 +1981,10 @@ package android.bluetooth {
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();

View File

@@ -2004,71 +2004,6 @@ public final class BluetoothAdapter {
return false;
}
/**
* 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
*

View File

@@ -1680,6 +1680,90 @@ public final class BluetoothDevice implements Parcelable, Attributable {
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.
*

View File

@@ -21,7 +21,7 @@ import android.annotation.SystemApi;
/**
* 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 {

View File

@@ -273,7 +273,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
mConnectAttempted = SystemClock.elapsedRealtime();
connectAllEnabledProfiles();
connectDevice();
}
public long getHiSyncId() {
@@ -371,7 +371,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
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 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
return;
}
mLocalAdapter.connectAllEnabledProfiles(mDevice);
mDevice.connect();
}
}
@@ -769,8 +769,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
* 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();