diff options
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
-rw-r--r-- | framework/java/android/bluetooth/BluetoothAdapter.java | 366 |
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(); |