diff options
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothAdapter.java')
-rw-r--r-- | framework/java/android/bluetooth/BluetoothAdapter.java | 161 |
1 files changed, 114 insertions, 47 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 6605a2e5f3..6b4c8062b6 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -59,7 +59,6 @@ import android.os.IBinder; import android.os.IpcDataCache; import android.os.ParcelUuid; import android.os.RemoteException; -import android.os.ResultReceiver; import android.sysprop.BluetoothProperties; import android.util.Log; import android.util.Pair; @@ -192,6 +191,16 @@ public final class BluetoothAdapter { STATE_BLE_TURNING_OFF }) @Retention(RetentionPolicy.SOURCE) + public @interface InternalAdapterState {} + + /** @hide */ + @IntDef(prefix = { "STATE_" }, value = { + STATE_OFF, + STATE_TURNING_ON, + STATE_ON, + STATE_TURNING_OFF, + }) + @Retention(RetentionPolicy.SOURCE) public @interface AdapterState {} /** @@ -272,14 +281,14 @@ public final class BluetoothAdapter { public @interface RfcommListenerResult {} /** - * Human-readable string helper for AdapterState + * Human-readable string helper for AdapterState and InternalAdapterState * * @hide */ @SystemApi @RequiresNoPermission @NonNull - public static String nameForState(@AdapterState int state) { + public static String nameForState(@InternalAdapterState int state) { switch (state) { case STATE_OFF: return "OFF"; @@ -741,6 +750,16 @@ public final class BluetoothAdapter { 3; //BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING; /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "STATE_" }, value = { + STATE_DISCONNECTED, + STATE_CONNECTING, + STATE_CONNECTED, + STATE_DISCONNECTING, + }) + public @interface ConnectionState {} + + /** @hide */ public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager"; private final IBinder mToken; @@ -824,6 +843,55 @@ public final class BluetoothAdapter { }; /** + * Interface for Bluetooth activity energy info listener. Should be implemented by applications + * and set when calling {@link BluetoothAdapter#requestControllerActivityEnergyInfo}. + * + * @hide + */ + @SystemApi + public interface OnBluetoothActivityEnergyInfoListener { + /** + * Called when Bluetooth activity energy info is available. + * Note: this listener is triggered at most once for each call to + * {@link #requestControllerActivityEnergyInfo}. + * + * @param info the latest {@link BluetoothActivityEnergyInfo}, or null if unavailable. + */ + void onBluetoothActivityEnergyInfo(@Nullable BluetoothActivityEnergyInfo info); + } + + private static class OnBluetoothActivityEnergyInfoProxy + extends IBluetoothActivityEnergyInfoListener.Stub { + private final Object mLock = new Object(); + @Nullable @GuardedBy("mLock") private Executor mExecutor; + @Nullable @GuardedBy("mLock") private OnBluetoothActivityEnergyInfoListener mListener; + + OnBluetoothActivityEnergyInfoProxy(Executor executor, + OnBluetoothActivityEnergyInfoListener listener) { + mExecutor = executor; + mListener = listener; + } + + @Override + public void onBluetoothActivityEnergyInfoAvailable(BluetoothActivityEnergyInfo info) { + Executor executor; + OnBluetoothActivityEnergyInfoListener listener; + synchronized (mLock) { + if (mExecutor == null || mListener == null) { + return; + } + executor = mExecutor; + listener = mListener; + // null out to allow garbage collection, prevent triggering listener more than once + mExecutor = null; + mListener = null; + } + Binder.clearCallingIdentity(); + executor.execute(() -> listener.onBluetoothActivityEnergyInfo(info)); + } + } + + /** * Get a handle to the default local Bluetooth adapter. * <p> * Currently Android only supports one Bluetooth adapter, but the API could @@ -1155,9 +1223,8 @@ public final class BluetoothAdapter { new IpcDataCache.QueryHandler<>() { @RequiresLegacyBluetoothPermission @RequiresNoPermission - @AdapterState @Override - public Integer apply(Void query) { + public @InternalAdapterState Integer apply(Void query) { int state = BluetoothAdapter.STATE_OFF; mServiceLock.readLock().lock(); try { @@ -1193,8 +1260,7 @@ public final class BluetoothAdapter { * Fetch the current bluetooth state. If the service is down, return * OFF. */ - @AdapterState - private int getStateInternal() { + private @InternalAdapterState int getStateInternal() { return mBluetoothGetStateCache.query(null); } @@ -1210,8 +1276,7 @@ public final class BluetoothAdapter { */ @RequiresLegacyBluetoothPermission @RequiresNoPermission - @AdapterState - public int getState() { + public @AdapterState int getState() { android.util.SeempLog.record(63); int state = getStateInternal(); @@ -1248,10 +1313,9 @@ public final class BluetoothAdapter { */ @RequiresLegacyBluetoothPermission @RequiresNoPermission - @AdapterState @UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine " + "whether you can use BLE & BT classic.") - public int getLeState() { + public @InternalAdapterState int getLeState() { int state = getStateInternal(); if (VDBG) { @@ -1490,31 +1554,40 @@ public final class BluetoothAdapter { * @return the UUIDs supported by the local Bluetooth Adapter. * @hide */ - @SystemApi + @UnsupportedAppUsage @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - @SuppressLint(value = {"ArrayReturn", "NullableCollection"}) public @NonNull ParcelUuid[] getUuids() { - if (getState() != STATE_ON) { - return new ParcelUuid[0]; + List<ParcelUuid> parcels = getUuidsList(); + return parcels.toArray(new ParcelUuid[parcels.size()]); + } + + /** + * Get the UUIDs supported by the local Bluetooth adapter. + * + * @return a list of the UUIDs supported by the local Bluetooth Adapter. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public @NonNull List<ParcelUuid> getUuidsList() { + List<ParcelUuid> defaultValue = new ArrayList<>(); + if (getState() != STATE_ON || mService == null) { + return defaultValue; } + mServiceLock.readLock().lock(); try { - mServiceLock.readLock().lock(); - if (mService != null) { - final SynchronousResultReceiver<List<ParcelUuid>> recv = - new SynchronousResultReceiver(); - mService.getUuids(mAttributionSource, recv); - List<ParcelUuid> parcels = recv.awaitResultNoInterrupt(getSyncTimeout()) - .getValue(new ArrayList<>()); - return parcels.toArray(new ParcelUuid[parcels.size()]); - } + final SynchronousResultReceiver<List<ParcelUuid>> recv = + new SynchronousResultReceiver(); + mService.getUuids(mAttributionSource, recv); + return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (RemoteException | TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); } finally { mServiceLock.readLock().unlock(); } - return new ParcelUuid[0]; + return defaultValue; } /** @@ -2690,7 +2763,9 @@ public final class BluetoothAdapter { * A null value for the activity info object may be sent if the bluetooth service is * unreachable or the device does not support reporting such information. * - * @param result The callback to which to send the activity info. + * @param executor the executor that the listener will be invoked on + * @param listener the listener that will receive the {@link BluetoothActivityEnergyInfo} + * object when it becomes available * @hide */ @SystemApi @@ -2699,22 +2774,22 @@ public final class BluetoothAdapter { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) - public void requestControllerActivityEnergyInfo(@NonNull ResultReceiver result) { - requireNonNull(result, "ResultReceiver cannot be null"); + public void requestControllerActivityEnergyInfo( + @NonNull @CallbackExecutor Executor executor, + @NonNull OnBluetoothActivityEnergyInfoListener listener) { + requireNonNull(executor, "executor cannot be null"); + requireNonNull(listener, "listener cannot be null"); try { mServiceLock.readLock().lock(); if (mService != null) { - mService.requestActivityInfo(result, mAttributionSource); - result = null; + mService.requestActivityInfo( + new OnBluetoothActivityEnergyInfoProxy(executor, listener), + mAttributionSource); } } catch (RemoteException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); } finally { mServiceLock.readLock().unlock(); - if (result != null) { - // Only send an immediate result if we failed. - result.send(0, null); - } } } @@ -2887,13 +2962,12 @@ public final class BluetoothAdapter { * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED} * intent to get the connection state of the adapter. * - * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link - * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED} + * @return the connection state * @hide */ @SystemApi @RequiresNoPermission - public int getConnectionState() { + public @ConnectionState int getConnectionState() { if (getState() != STATE_ON) { return BluetoothAdapter.STATE_DISCONNECTED; } @@ -2949,17 +3023,13 @@ public final class BluetoothAdapter { * is connected to any remote device for a specific profile. * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. * - * <p> Return value can be one of - * {@link BluetoothProfile#STATE_DISCONNECTED}, - * {@link BluetoothProfile#STATE_CONNECTING}, - * {@link BluetoothProfile#STATE_CONNECTED}, - * {@link BluetoothProfile#STATE_DISCONNECTING} + * <p> Return the profile connection state */ @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @SuppressLint("AndroidFrameworkRequiresPermission") - public int getProfileConnectionState(int profile) { + public @ConnectionState int getProfileConnectionState(int profile) { android.util.SeempLog.record(64); if (getState() != STATE_ON) { return BluetoothProfile.STATE_DISCONNECTED; @@ -4351,7 +4421,6 @@ public final class BluetoothAdapter { * @hide */ @RequiresNoPermission - @SystemApi public boolean registerServiceLifecycleCallback(@NonNull ServiceLifecycleCallback callback) { return getBluetoothService(callback.mRemote) != null; } @@ -4362,7 +4431,6 @@ public final class BluetoothAdapter { * @hide */ @RequiresNoPermission - @SystemApi public void unregisterServiceLifecycleCallback(@NonNull ServiceLifecycleCallback callback) { removeServiceStateCallback(callback.mRemote); } @@ -4372,7 +4440,6 @@ public final class BluetoothAdapter { * * @hide */ - @SystemApi public abstract static class ServiceLifecycleCallback { /** Called when the bluetooth stack is up */ @@ -4985,7 +5052,7 @@ public final class BluetoothAdapter { * Returns human-readable strings corresponding to {@link DisconnectReason}. */ @NonNull - public static String disconnectReasonText(@DisconnectReason int reason) { + public static String disconnectReasonToString(@DisconnectReason int reason) { switch (reason) { case BluetoothStatusCodes.ERROR_UNKNOWN: return "Reason unknown"; |