summaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothAdapter.java
diff options
context:
space:
mode:
authorDaniel Norman <danielnorman@google.com>2022-03-17 15:56:15 -0700
committerDaniel Norman <danielnorman@google.com>2022-03-17 16:00:48 -0700
commit716968a4d1de6971c5c569cd8f5f2830b5dba575 (patch)
treeb5dfc1a84427b07b42d6eb0c4592611dcc419930 /framework/java/android/bluetooth/BluetoothAdapter.java
parenta1ee0132fb60762afd5e6a2d8259cec2a549aea3 (diff)
parent6c897e526322043f504c6a3ff9fd4524f3f59d4b (diff)
Merge TP1A.220310.002
Change-Id: If2f3a2a6833c45ec4c0cba7c7e668a487938cb92
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
-rw-r--r--framework/java/android/bluetooth/BluetoothAdapter.java366
1 files changed, 167 insertions, 199 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index dc7ffa6fd2..6605a2e5f3 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -30,7 +30,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
-import android.annotation.SystemApi; //import android.app.PropertyInvalidatedCache;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice.AddressType;
import android.bluetooth.BluetoothDevice.Transport;
@@ -56,6 +56,7 @@ import android.os.Binder;
import android.os.BluetoothServiceManager;
import android.os.Build;
import android.os.IBinder;
+import android.os.IpcDataCache;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -1127,45 +1128,66 @@ public final class BluetoothAdapter {
return false;
}
- /*
- private static final String BLUETOOTH_GET_STATE_CACHE_PROPERTY = "cache_key.bluetooth.get_state";
+ /**
+ * There are several instances of IpcDataCache used in this class.
+ * BluetoothCache wraps up the common code. All caches are created with a maximum of
+ * eight entries, and the key is in the bluetooth module. The name is set to the api.
+ */
+ private static class BluetoothCache<Q, R> extends IpcDataCache<Q, R> {
+ BluetoothCache(String api, IpcDataCache.QueryHandler query) {
+ super(8, IpcDataCache.MODULE_BLUETOOTH, api, api, query);
+ }};
- private final PropertyInvalidatedCache<Void, Integer> mBluetoothGetStateCache =
- new PropertyInvalidatedCache<Void, Integer>(
- 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public Integer recompute(Void query) {
- try {
- final SynchronousResultReceiver<Integer> recv =
- new SynchronousResultReceiver();
- mService.getState(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout())
- .getValue(BluetoothAdapter.STATE_OFF);
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- return BluetoothAdapter.STATE_OFF;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- };
+ /**
+ * Invalidate a bluetooth cache. This method is just a short-hand wrapper that
+ * enforces the bluetooth module.
*/
+ private static void invalidateCache(@NonNull String api) {
+ IpcDataCache.invalidateCache(IpcDataCache.MODULE_BLUETOOTH, api);
+ }
+
+ /**
+ * The binder cache for getState().
+ */
+ private static final String GET_STATE_API = "getState";
+
+ private final IpcDataCache.QueryHandler<Void, Integer> mBluetoothGetStateQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
+ @AdapterState
+ @Override
+ public Integer apply(Void query) {
+ int state = BluetoothAdapter.STATE_OFF;
+ mServiceLock.readLock().lock();
+ try {
+ if (mService != null) {
+ final SynchronousResultReceiver<Integer> recv =
+ new SynchronousResultReceiver();
+ mService.getState(recv);
+ return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(state);
+ }
+ } catch (RemoteException | TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return state;
+ }};
+
+ private final IpcDataCache<Void, Integer> mBluetoothGetStateCache =
+ new BluetoothCache<Void, Integer>(GET_STATE_API, mBluetoothGetStateQuery);
/** @hide */
- /*
@RequiresNoPermission
public void disableBluetoothGetStateCache() {
- mBluetoothGetStateCache.disableLocal();
+ mBluetoothGetStateCache.disableForCurrentProcess();
}
- */
/** @hide */
- /*
public static void invalidateBluetoothGetStateCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_GET_STATE_CACHE_PROPERTY);
+ invalidateCache(GET_STATE_API);
}
- */
/**
* Fetch the current bluetooth state. If the service is down, return
@@ -1173,22 +1195,7 @@ public final class BluetoothAdapter {
*/
@AdapterState
private int getStateInternal() {
- int state = BluetoothAdapter.STATE_OFF;
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- //state = mBluetoothGetStateCache.query(null);
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- //return mBluetoothBondCache.query(this);
- mService.getState(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(state);
- }
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
- }
- return state;
+ return mBluetoothGetStateCache.query(null);
}
/**
@@ -1488,9 +1495,9 @@ public final class BluetoothAdapter {
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SuppressLint(value = {"ArrayReturn", "NullableCollection"})
- public @Nullable ParcelUuid[] getUuids() {
+ public @NonNull ParcelUuid[] getUuids() {
if (getState() != STATE_ON) {
- return null;
+ return new ParcelUuid[0];
}
try {
mServiceLock.readLock().lock();
@@ -1507,7 +1514,7 @@ public final class BluetoothAdapter {
} finally {
mServiceLock.readLock().unlock();
}
- return null;
+ return new ParcelUuid[0];
}
/**
@@ -2280,48 +2287,42 @@ public final class BluetoothAdapter {
}
}
- /*
- private static final String BLUETOOTH_FILTERING_CACHE_PROPERTY =
- "cache_key.bluetooth.is_offloaded_filtering_supported";
- private final PropertyInvalidatedCache<Void, Boolean> mBluetoothFilteringCache =
- new PropertyInvalidatedCache<Void, Boolean>(
- 8, BLUETOOTH_FILTERING_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public Boolean recompute(Void query) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- final SynchronousResultReceiver<Boolean> recv =
- new SynchronousResultReceiver();
- mService.isOffloadedFilteringSupported(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false);
- }
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
-
+ private final IpcDataCache.QueryHandler<Void, Boolean> mBluetoothFilteringQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
+ @Override
+ public Boolean apply(Void query) {
+ mServiceLock.readLock().lock();
+ try {
+ if (mService != null) {
+ final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
+ mService.isOffloadedFilteringSupported(recv);
+ return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false);
}
- };
- */
+ } catch (RemoteException | TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return false;
+ }};
+
+ private static final String FILTERING_API = "isOffloadedFilteringSupported";
+
+ private final IpcDataCache<Void, Boolean> mBluetoothFilteringCache =
+ new BluetoothCache<Void, Boolean>(FILTERING_API, mBluetoothFilteringQuery);
/** @hide */
- /*
@RequiresNoPermission
public void disableIsOffloadedFilteringSupportedCache() {
- mBluetoothFilteringCache.disableLocal();
+ mBluetoothFilteringCache.disableForCurrentProcess();
}
- */
/** @hide */
- /*
public static void invalidateIsOffloadedFilteringSupportedCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_FILTERING_CACHE_PROPERTY);
+ invalidateCache(FILTERING_API);
}
- */
/**
* Return true if offloaded filters are supported
@@ -2334,22 +2335,7 @@ public final class BluetoothAdapter {
if (!getLeAccess()) {
return false;
}
- //return mBluetoothFilteringCache.query(null);
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- mService.isOffloadedFilteringSupported(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(false);
- }
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return false;
+ return mBluetoothFilteringCache.query(null);
}
/**
@@ -2498,6 +2484,7 @@ public final class BluetoothAdapter {
* supported, or an error code.
*
* @return whether the LE audio is supported
+ * @throws IllegalStateException if the bluetooth service is null
*/
@RequiresNoPermission
public @LeFeatureReturnValues int isLeAudioSupported() {
@@ -2511,6 +2498,9 @@ public final class BluetoothAdapter {
mService.isLeAudioSupported(recv);
return recv.awaitResultNoInterrupt(getSyncTimeout())
.getValue(BluetoothStatusCodes.ERROR_UNKNOWN);
+ } else {
+ throw new IllegalStateException(
+ "LE state is on, but there is no bluetooth service.");
}
} catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
@@ -2528,6 +2518,7 @@ public final class BluetoothAdapter {
* is not supported, or an error code.
*
* @return whether the LE audio broadcast source is supported
+ * @throws IllegalStateException if the bluetooth service is null
*/
@RequiresNoPermission
public @LeFeatureReturnValues int isLeAudioBroadcastSourceSupported() {
@@ -2541,6 +2532,9 @@ public final class BluetoothAdapter {
mService.isLeAudioBroadcastSourceSupported(recv);
return recv.awaitResultNoInterrupt(getSyncTimeout())
.getValue(BluetoothStatusCodes.ERROR_UNKNOWN);
+ } else {
+ throw new IllegalStateException(
+ "LE state is on, but there is no bluetooth service.");
}
} catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
@@ -2559,6 +2553,7 @@ public final class BluetoothAdapter {
* not supported, or an error code.
*
* @return whether the LE audio broadcast assistent is supported
+ * @throws IllegalStateException if the bluetooth service is null
*/
@RequiresNoPermission
public @LeFeatureReturnValues int isLeAudioBroadcastAssistantSupported() {
@@ -2572,6 +2567,9 @@ public final class BluetoothAdapter {
mService.isLeAudioBroadcastAssistantSupported(recv);
return recv.awaitResultNoInterrupt(getSyncTimeout())
.getValue(BluetoothStatusCodes.ERROR_UNKNOWN);
+ } else {
+ throw new IllegalStateException(
+ "LE state is on, but there is no bluetooth service.");
}
} catch (TimeoutException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
@@ -2840,47 +2838,46 @@ public final class BluetoothAdapter {
return supportedProfiles;
}
- /*
- private static final String BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY =
- "cache_key.bluetooth.get_adapter_connection_state";
- private final PropertyInvalidatedCache<Void, Integer>
- mBluetoothGetAdapterConnectionStateCache =
- new PropertyInvalidatedCache<Void, Integer> (
- 8, BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public Integer recompute(Void query) {
- try {
- final SynchronousResultReceiver<Integer> recv =
- new SynchronousResultReceiver();
- mService.getAdapterConnectionState(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout())
- .getValue(BluetoothAdapter.STATE_DISCONNECTED);
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- return BluetoothAdapter.STATE_DISCONNECTED;
+ private final IpcDataCache.QueryHandler<Void, Integer> mBluetoothGetAdapterQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
+ @Override
+ public Integer apply(Void query) {
+ mServiceLock.readLock().lock();
+ try {
+ if (mService != null) {
+ final SynchronousResultReceiver<Integer> recv =
+ new SynchronousResultReceiver();
+ mService.getAdapterConnectionState(recv);
+ return recv.awaitResultNoInterrupt(getSyncTimeout())
+ .getValue(STATE_DISCONNECTED);
}
- };
- */
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to getConnectionState, error: ", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return BluetoothAdapter.STATE_DISCONNECTED;
+ }};
+
+ private static final String GET_CONNECTION_API = "getAdapterConnectionState";
+ private final IpcDataCache<Void, Integer>
+ mBluetoothGetAdapterConnectionStateCache =
+ new BluetoothCache<Void, Integer>(GET_CONNECTION_API, mBluetoothGetAdapterQuery);
/** @hide */
- /*
@RequiresNoPermission
public void disableGetAdapterConnectionStateCache() {
- mBluetoothGetAdapterConnectionStateCache.disableLocal();
+ mBluetoothGetAdapterConnectionStateCache.disableForCurrentProcess();
}
- */
/** @hide */
- /*
public static void invalidateGetAdapterConnectionStateCache() {
- PropertyInvalidatedCache.invalidateCache(
- BLUETOOTH_GET_ADAPTER_CONNECTION_STATE_CACHE_PROPERTY);
+ invalidateCache(GET_CONNECTION_API);
}
- */
/**
* Get the current connection state of the local Bluetooth adapter.
@@ -2900,72 +2897,51 @@ public final class BluetoothAdapter {
if (getState() != STATE_ON) {
return BluetoothAdapter.STATE_DISCONNECTED;
}
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- mService.getAdapterConnectionState(recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(STATE_DISCONNECTED);
- }
- //return mBluetoothGetAdapterConnectionStateCache.query(null);
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } catch (RemoteException e) {
- Log.e(TAG, "failed to getConnectionState, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothAdapter.STATE_DISCONNECTED;
+ return mBluetoothGetAdapterConnectionStateCache.query(null);
}
- /*
- private static final String BLUETOOTH_PROFILE_CACHE_PROPERTY =
- "cache_key.bluetooth.get_profile_connection_state";
- private final PropertyInvalidatedCache<Integer, Integer>
- mGetProfileConnectionStateCache =
- new PropertyInvalidatedCache<Integer, Integer>(
- 8, BLUETOOTH_PROFILE_CACHE_PROPERTY) {
- @Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
- public Integer recompute(Integer query) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- final SynchronousResultReceiver<Integer> recv =
- new SynchronousResultReceiver();
- mService.getProfileConnectionState(query, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout())
- .getValue(BluetoothProfile.STATE_DISCONNECTED);
- }
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothProfile.STATE_DISCONNECTED;
- }
- @Override
- public String queryToString(Integer query) {
- return String.format("getProfileConnectionState(profile=\"%d\")",
- query);
+ private final IpcDataCache.QueryHandler<Integer, Integer> mBluetoothProfileQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @RequiresNoPermission
+ @Override
+ public Integer apply(Integer query) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
+ mService.getProfileConnectionState(query, recv);
+ return recv.awaitResultNoInterrupt(getSyncTimeout())
+ .getValue(BluetoothProfile.STATE_DISCONNECTED);
}
- };
- */
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to getProfileConnectionState, error: ", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }};
- /** @hide */
- /*
+ private static final String PROFILE_API = "getProfileConnectionState";
+ private final IpcDataCache<Integer, Integer>
+ mGetProfileConnectionStateCache =
+ new BluetoothCache<Integer, Integer>(PROFILE_API, mBluetoothProfileQuery);
+
+ /**
+ * @hide
+ */
@RequiresNoPermission
public void disableGetProfileConnectionStateCache() {
- mGetProfileConnectionStateCache.disableLocal();
+ mGetProfileConnectionStateCache.disableForCurrentProcess();
}
- */
- /** @hide */
- /*
+ /**
+ * @hide
+ */
public static void invalidateGetProfileConnectionStateCache() {
- PropertyInvalidatedCache.invalidateCache(BLUETOOTH_PROFILE_CACHE_PROPERTY);
+ invalidateCache(PROFILE_API);
}
- */
/**
* Get the current connection state of a profile.
@@ -2988,22 +2964,7 @@ public final class BluetoothAdapter {
if (getState() != STATE_ON) {
return BluetoothProfile.STATE_DISCONNECTED;
}
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
- mService.getProfileConnectionState(profile, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(STATE_DISCONNECTED);
- }
- //return mGetProfileConnectionStateCache.query(new Integer(profile));
- } catch (TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- } catch (RemoteException e) {
- Log.e(TAG, "failed to getProfileConnectionState, error: ", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
- return BluetoothProfile.STATE_DISCONNECTED;
+ return mGetProfileConnectionStateCache.query(profile);
}
/**
@@ -3648,6 +3609,9 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.LE_AUDIO) {
BluetoothLeAudio leAudio = new BluetoothLeAudio(context, listener, this);
return true;
+ } else if (profile == BluetoothProfile.LE_AUDIO_BROADCAST) {
+ BluetoothLeBroadcast leAudio = new BluetoothLeBroadcast(context, listener);
+ return true;
} else if (profile == BluetoothProfile.VOLUME_CONTROL) {
BluetoothVolumeControl vcs = new BluetoothVolumeControl(context, listener, this);
return true;
@@ -3765,6 +3729,10 @@ public final class BluetoothAdapter {
BluetoothLeAudio leAudio = (BluetoothLeAudio) proxy;
leAudio.close();
break;
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ BluetoothLeBroadcast leAudioBroadcast = (BluetoothLeBroadcast) proxy;
+ leAudioBroadcast.close();
+ break;
case BluetoothProfile.GROUP_CLIENT:
BluetoothDeviceGroup groupClient = (BluetoothDeviceGroup) proxy;
groupClient.close();