diff options
| author | Ugo Yu <ugoyu@google.com> | 2019-03-05 16:20:27 +0800 |
|---|---|---|
| committer | Ugo Yu <ugoyu@google.com> | 2019-04-08 20:09:53 +0800 |
| commit | 4741a8bd53ebf7c33ef854aeede526e627e0d0df (patch) | |
| tree | b91b118b08c7395208f42d92ad8ddeefa1fddf0c /core/java/android | |
| parent | 835f260d602a319e6670911ff3887f5c6247b33d (diff) | |
Refine Bluetooth Metadata API
- Modify MetadataListener to as an interface and rename
it to OnMetadataChangedListener
- Fix typo UNTHETHERED -> UNTETHERED
- Add NonNull annotation for metadata API parameters
- Re-design metadata unregister API
- Change metadata type to byte array
Bug: 124448651
Bug: 126701203
Bug: 126699213
Test: build pass
Change-Id: I79460071c7693f648e92cf849738c24f8bc269d9
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 116 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothDevice.java | 67 |
2 files changed, 108 insertions, 75 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index b8a741ab2b72..31bbd16497cb 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -20,6 +20,7 @@ package android.bluetooth; import android.Manifest; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -37,7 +38,6 @@ import android.bluetooth.le.ScanSettings; import android.content.Context; import android.os.BatteryStats; import android.os.Binder; -import android.os.Handler; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; @@ -61,6 +61,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -650,7 +651,7 @@ public final class BluetoothAdapter { private final Object mLock = new Object(); private final Map<LeScanCallback, ScanCallback> mLeScanClients; - private static final Map<BluetoothDevice, List<Pair<MetadataListener, Handler>>> + private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>> sMetadataListeners = new HashMap<>(); /** @@ -660,14 +661,15 @@ public final class BluetoothAdapter { private static final IBluetoothMetadataListener sBluetoothMetadataListener = new IBluetoothMetadataListener.Stub() { @Override - public void onMetadataChanged(BluetoothDevice device, int key, String value) { + public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) { synchronized (sMetadataListeners) { if (sMetadataListeners.containsKey(device)) { - List<Pair<MetadataListener, Handler>> list = sMetadataListeners.get(device); - for (Pair<MetadataListener, Handler> pair : list) { - MetadataListener listener = pair.first; - Handler handler = pair.second; - handler.post(() -> { + List<Pair<OnMetadataChangedListener, Executor>> list = + sMetadataListeners.get(device); + for (Pair<OnMetadataChangedListener, Executor> pair : list) { + OnMetadataChangedListener listener = pair.first; + Executor executor = pair.second; + executor.execute(() -> { listener.onMetadataChanged(device, key, value); }); } @@ -3153,30 +3155,30 @@ public final class BluetoothAdapter { } /** - * Register a {@link #MetadataListener} to receive update about metadata + * Register a {@link #OnMetadataChangedListener} to receive update about metadata * changes for this {@link BluetoothDevice}. * Registration must be done when Bluetooth is ON and will last until - * {@link #unregisterMetadataListener(BluetoothDevice)} is called, even when Bluetooth + * {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when Bluetooth * restarted in the middle. * All input parameters should not be null or {@link NullPointerException} will be triggered. - * The same {@link BluetoothDevice} and {@link #MetadataListener} pair can only be registered - * once, double registration would cause {@link IllegalArgumentException}. + * The same {@link BluetoothDevice} and {@link #OnMetadataChangedListener} pair can only be + * registered once, double registration would cause {@link IllegalArgumentException}. * * @param device {@link BluetoothDevice} that will be registered - * @param listener {@link #MetadataListener} that will receive asynchronous callbacks - * @param handler the handler for listener callback + * @param executor the executor for listener callback + * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks * @return true on success, false on error - * @throws NullPointerException If one of {@code listener}, {@code device} or {@code handler} + * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor} * is null. - * @throws IllegalArgumentException The same {@link #MetadataListener} and + * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and * {@link BluetoothDevice} are registered twice. * @hide */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public boolean registerMetadataListener(BluetoothDevice device, MetadataListener listener, - Handler handler) { - if (DBG) Log.d(TAG, "registerMetdataListener()"); + public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device, + @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) { + if (DBG) Log.d(TAG, "addOnMetadataChangedListener()"); final IBluetooth service = mService; if (service == null) { @@ -3189,14 +3191,15 @@ public final class BluetoothAdapter { if (device == null) { throw new NullPointerException("device is null"); } - if (handler == null) { - throw new NullPointerException("handler is null"); + if (executor == null) { + throw new NullPointerException("executor is null"); } synchronized (sMetadataListeners) { - List<Pair<MetadataListener, Handler>> listenerList = sMetadataListeners.get(device); + List<Pair<OnMetadataChangedListener, Executor>> listenerList = + sMetadataListeners.get(device); if (listenerList == null) { - // Create new listener/handler list for registeration + // Create new listener/executor list for registeration listenerList = new ArrayList<>(); sMetadataListeners.put(device, listenerList); } else { @@ -3207,7 +3210,7 @@ public final class BluetoothAdapter { } } - Pair<MetadataListener, Handler> listenerPair = new Pair(listener, handler); + Pair<OnMetadataChangedListener, Executor> listenerPair = new Pair(listener, executor); listenerList.add(listenerPair); boolean ret = false; @@ -3230,63 +3233,74 @@ public final class BluetoothAdapter { } /** - * Unregister all {@link MetadataListener} from this {@link BluetoothDevice}. + * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}. * Unregistration can be done when Bluetooth is either ON or OFF. - * {@link #registerMetadataListener(MetadataListener, BluetoothDevice, Handler)} must - * be called before unregisteration. - * Unregistering a device that is not regestered would cause {@link IllegalArgumentException}. + * {@link #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)} + * must be called before unregisteration. * - * @param device {@link BluetoothDevice} that will be unregistered. it + * @param device {@link BluetoothDevice} that will be unregistered. It + * should not be null or {@link NullPointerException} will be triggered. + * @param listener {@link OnMetadataChangedListener} that will be unregistered. It * should not be null or {@link NullPointerException} will be triggered. * @return true on success, false on error - * @throws NullPointerException If {@code device} is null. + * @throws NullPointerException If {@code listener} or {@code device} is null. * @throws IllegalArgumentException If {@code device} has not been registered before. * @hide */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public boolean unregisterMetadataListener(BluetoothDevice device) { - if (DBG) Log.d(TAG, "unregisterMetdataListener()"); + public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device, + @NonNull OnMetadataChangedListener listener) { + if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()"); if (device == null) { throw new NullPointerException("device is null"); } + if (listener == null) { + throw new NullPointerException("listener is null"); + } synchronized (sMetadataListeners) { - if (sMetadataListeners.containsKey(device)) { - sMetadataListeners.remove(device); - } else { + if (!sMetadataListeners.containsKey(device)) { throw new IllegalArgumentException("device was not registered"); } + // Remove issued listener from the registered device + sMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener))); - final IBluetooth service = mService; - if (service == null) { - // Bluetooth is OFF, do nothing to Bluetooth service. - return true; - } - try { - return service.unregisterMetadataListener(device); - } catch (RemoteException e) { - Log.e(TAG, "unregisterMetadataListener fail", e); - return false; + if (sMetadataListeners.get(device).isEmpty()) { + // Unregister to Bluetooth service if all listeners are removed from + // the registered device + sMetadataListeners.remove(device); + final IBluetooth service = mService; + if (service == null) { + // Bluetooth is OFF, do nothing to Bluetooth service. + return true; + } + try { + return service.unregisterMetadataListener(device); + } catch (RemoteException e) { + Log.e(TAG, "unregisterMetadataListener fail", e); + return false; + } } } + return true; } /** - * This abstract class is used to implement {@link BluetoothAdapter} metadata listener. + * This interface is used to implement {@link BluetoothAdapter} metadata listener. * @hide */ @SystemApi - public abstract static class MetadataListener { + public interface OnMetadataChangedListener { /** * Callback triggered if the metadata of {@link BluetoothDevice} registered in - * {@link #registerMetadataListener}. + * {@link #addOnMetadataChangedListener}. * * @param device changed {@link BluetoothDevice}. * @param key changed metadata key, one of BluetoothDevice.METADATA_*. - * @param value the new value of metadata. + * @param value the new value of metadata as byte array. */ - public void onMetadataChanged(BluetoothDevice device, int key, String value) { - } + void onMetadataChanged(@NonNull BluetoothDevice device, int key, + @Nullable byte[] value); } } diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 204d7e3ceca6..74ceeb92f751 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -18,6 +18,7 @@ package android.bluetooth; import android.Manifest; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; @@ -351,6 +352,7 @@ public final class BluetoothDevice implements Parcelable { /** * Manufacturer name of this Bluetooth device + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi @@ -358,6 +360,7 @@ public final class BluetoothDevice implements Parcelable { /** * Model name of this Bluetooth device + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi @@ -365,6 +368,7 @@ public final class BluetoothDevice implements Parcelable { /** * Software version of this Bluetooth device + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi @@ -372,6 +376,7 @@ public final class BluetoothDevice implements Parcelable { /** * Hardware version of this Bluetooth device + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi @@ -379,6 +384,7 @@ public final class BluetoothDevice implements Parcelable { /** * Package name of the companion app, if any + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi @@ -386,6 +392,7 @@ public final class BluetoothDevice implements Parcelable { /** * URI to the main icon shown on the settings UI + * Data type should be {@link Byte} array. * @hide */ @SystemApi @@ -393,80 +400,91 @@ public final class BluetoothDevice implements Parcelable { /** * Whether this device is an untethered headset with left, right and case + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_IS_UNTHETHERED_HEADSET = 6; + public static final int METADATA_IS_UNTETHERED_HEADSET = 6; /** * URI to icon of the left headset + * Data type should be {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_LEFT_ICON = 7; + public static final int METADATA_UNTETHERED_LEFT_ICON = 7; /** * URI to icon of the right headset + * Data type should be {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_RIGHT_ICON = 8; + public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; /** * URI to icon of the headset charging case + * Data type should be {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_CASE_ICON = 9; + public static final int METADATA_UNTETHERED_CASE_ICON = 9; /** - * Battery level (0-100), {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN} - * is invalid, of the left headset + * Battery level of left headset + * Data type should be {@String} 0-100 as {@link Byte} array, otherwise + * as invalid. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_LEFT_BATTERY = 10; + public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; /** - * Battery level (0-100), {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN} - * is invalid, of the right headset + * Battery level of rigth headset + * Data type should be {@String} 0-100 as {@link Byte} array, otherwise + * as invalid. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_RIGHT_BATTERY = 11; + public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; /** - * Battery level (0-100), {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN} - * is invalid, of the headset charging case + * Battery level of the headset charging case + * Data type should be {@String} 0-100 as {@link Byte} array, otherwise + * as invalid. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_CASE_BATTERY = 12; + public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; /** * Whether the left headset is charging + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_LEFT_CHARGING = 13; + public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; /** * Whether the right headset is charging + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_RIGHT_CHARGING = 14; + public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; /** * Whether the headset charging case is charging + * Data type should be {@String} as {@link Byte} array. * @hide */ @SystemApi - public static final int METADATA_UNTHETHERED_CASE_CHARGING = 15; + public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; /** - * URI to the enhanced settings UI slice, null or empty String means - * the UI does not exist + * URI to the enhanced settings UI slice + * Data type should be {@String} as {@link Byte} array, null means + * the UI does not exist. * @hide */ @SystemApi @@ -2243,21 +2261,21 @@ public final class BluetoothDevice implements Parcelable { * {@link #BOND_NONE}. * * @param key must be within the list of BluetoothDevice.METADATA_* - * @param value the string data to set for key. Must be less than + * @param value a byte array data to set for key. Must be less than * {@link BluetoothAdapter#METADATA_MAX_LENGTH} characters in length * @return true on success, false on error * @hide */ @SystemApi @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public boolean setMetadata(int key, String value) { + public boolean setMetadata(int key, @NonNull byte[] value) { final IBluetooth service = sService; if (service == null) { Log.e(TAG, "Bluetooth is not enabled. Cannot set metadata"); return false; } - if (value.length() > METADATA_MAX_LENGTH) { - throw new IllegalArgumentException("value length is " + value.length() + if (value.length > METADATA_MAX_LENGTH) { + throw new IllegalArgumentException("value length is " + value.length + ", should not over " + METADATA_MAX_LENGTH); } try { @@ -2272,12 +2290,13 @@ public final class BluetoothDevice implements Parcelable { * Get a keyed metadata for this {@link BluetoothDevice} as {@link String} * * @param key must be within the list of BluetoothDevice.METADATA_* - * @return Metadata of the key as string, null on error or not found + * @return Metadata of the key as byte array, null on error or not found * @hide */ @SystemApi + @Nullable @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) - public String getMetadata(int key) { + public byte[] getMetadata(int key) { final IBluetooth service = sService; if (service == null) { Log.e(TAG, "Bluetooth is not enabled. Cannot get metadata"); |
