summaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothMapClient.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothMapClient.java')
-rw-r--r--framework/java/android/bluetooth/BluetoothMapClient.java98
1 files changed, 83 insertions, 15 deletions
diff --git a/framework/java/android/bluetooth/BluetoothMapClient.java b/framework/java/android/bluetooth/BluetoothMapClient.java
index 03536f9aad..b29d7b0413 100644
--- a/framework/java/android/bluetooth/BluetoothMapClient.java
+++ b/framework/java/android/bluetooth/BluetoothMapClient.java
@@ -18,12 +18,12 @@ package android.bluetooth;
import static android.bluetooth.BluetoothUtils.getSyncTimeout;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
@@ -34,6 +34,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.CloseGuard;
import android.util.Log;
import com.android.modules.utils.SynchronousResultReceiver;
@@ -49,15 +50,37 @@ import java.util.concurrent.TimeoutException;
* @hide
*/
@SystemApi
-public final class BluetoothMapClient implements BluetoothProfile {
+public final class BluetoothMapClient implements BluetoothProfile, AutoCloseable {
private static final String TAG = "BluetoothMapClient";
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
- /** @hide */
+ private final CloseGuard mCloseGuard;
+
+ /**
+ * Intent used to broadcast the change in connection state of the MAP Client profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SuppressLint("ActionValue")
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
@@ -197,6 +220,16 @@ public final class BluetoothMapClient implements BluetoothProfile {
mAdapter = adapter;
mAttributionSource = adapter.getAttributionSource();
mProfileConnector.connect(context, listener);
+ mCloseGuard = new CloseGuard();
+ mCloseGuard.open("close");
+ }
+
+ /** @hide */
+ protected void finalize() {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ close();
}
/**
@@ -208,6 +241,9 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public void close() {
mProfileConnector.disconnect();
+ if (mCloseGuard != null) {
+ mCloseGuard.close();
+ }
}
private IBluetoothMapClient getService() {
@@ -309,10 +345,14 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return list of connected devices
* @hide
*/
+ @SystemApi
@Override
@RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getConnectedDevices() {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
final IBluetoothMapClient service = getService();
final List<BluetoothDevice> defaultValue = new ArrayList<>();
@@ -327,7 +367,10 @@ public final class BluetoothMapClient implements BluetoothProfile {
return Attributable.setAttributionSource(
recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}
@@ -337,13 +380,19 @@ public final class BluetoothMapClient implements BluetoothProfile {
/**
* Get the list of devices matching specified states. Currently at most one.
*
+ * @param states The connection states to match for.
* @return list of matching devices
* @hide
*/
+ @SystemApi
@Override
@RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public
+ @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
final IBluetoothMapClient service = getService();
final List<BluetoothDevice> defaultValue = new ArrayList<>();
@@ -358,7 +407,10 @@ public final class BluetoothMapClient implements BluetoothProfile {
return Attributable.setAttributionSource(
recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
mAttributionSource);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}
@@ -368,13 +420,18 @@ public final class BluetoothMapClient implements BluetoothProfile {
/**
* Get connection state of device
*
+ * @param device The remote device whose connection state is to be ascertained.
* @return device connection state
* @hide
*/
+ @SystemApi
@Override
@RequiresBluetoothConnectPermission
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- public int getConnectionState(BluetoothDevice device) {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
final IBluetoothMapClient service = getService();
final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
@@ -386,7 +443,10 @@ public final class BluetoothMapClient implements BluetoothProfile {
final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver<>();
service.getConnectionState(device, mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}
@@ -426,6 +486,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return true if connectionPolicy is set, false on error
* @hide
*/
+ @SystemApi
@RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
@@ -446,7 +507,10 @@ public final class BluetoothMapClient implements BluetoothProfile {
final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
service.setConnectionPolicy(device, connectionPolicy, mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}
@@ -484,6 +548,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return connection policy of the device
* @hide
*/
+ @SystemApi
@RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
@@ -501,7 +566,10 @@ public final class BluetoothMapClient implements BluetoothProfile {
final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
service.getConnectionPolicy(device, mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
}
}