summaryrefslogtreecommitdiff
path: root/framework/java
diff options
context:
space:
mode:
authorJack He <siyuanh@google.com>2022-04-24 19:02:37 -0700
committerJack He <siyuanh@google.com>2022-04-28 01:28:14 +0000
commit771724d4575abe529b6bd1a071e3289f14d3d77a (patch)
tree4f3fd5cb599be1eb0984988d399f949596e9b299 /framework/java
parent376819760a772a3fdf299811aad92988db6c1f8a (diff)
BASS: Fix BASS client service to pass CTS tests
* Through NullPointerException when asserting on non-null arguments * Invoke error callback when sink device is not connected * Assert on parameter value at binder client side * Clear binder identity when checking DeviceConfig values Test: atest CtsBluetoothTestCases Bug: 229790402 Fixes: 229790402 Ignore-AOSP-First: Fixing CTS tests on T Change-Id: Ie19cf24d2fe20948494643f3ce179d1a2c3a290f Merged-In: Ie19cf24d2fe20948494643f3ce179d1a2c3a290f (cherry picked from commit 9d0518ee6515bf0aeccdbd428485e7bd38f68f0b)
Diffstat (limited to 'framework/java')
-rw-r--r--framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java18
-rwxr-xr-xframework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java69
-rwxr-xr-xframework/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java22
-rw-r--r--framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java17
-rw-r--r--framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java25
-rw-r--r--framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java18
6 files changed, 152 insertions, 17 deletions
diff --git a/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java b/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java
index 4f02e89312..17d99ae72d 100644
--- a/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java
+++ b/framework/java/android/bluetooth/BluetoothLeAudioContentMetadata.java
@@ -25,7 +25,9 @@ import android.os.Parcelable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* A class representing the media metadata information defined in the Basic Audio Profile.
@@ -50,6 +52,22 @@ public final class BluetoothLeAudioContentMetadata implements Parcelable {
mRawMetadata = rawMetadata;
}
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (!(o instanceof BluetoothLeAudioContentMetadata)) {
+ return false;
+ }
+ final BluetoothLeAudioContentMetadata other = (BluetoothLeAudioContentMetadata) o;
+ return Objects.equals(mProgramInfo, other.getProgramInfo())
+ && Objects.equals(mLanguage, other.getLanguage())
+ && Arrays.equals(mRawMetadata, other.getRawMetadata());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mProgramInfo, mLanguage, mRawMetadata);
+ }
+
/**
* Get the title and/or summary of Audio Stream content in UTF-8 format.
*
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java
index 70955252ea..05716eb6b1 100755
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java
@@ -363,6 +363,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
@Override
public @BluetoothProfile.BtProfileState int getConnectionState(@NonNull BluetoothDevice sink) {
log("getConnectionState(" + sink + ")");
+ Objects.requireNonNull(sink, "sink cannot be null");
final IBluetoothLeBroadcastAssistant service = getService();
final int defaultValue = BluetoothProfile.STATE_DISCONNECTED;
if (service == null) {
@@ -392,6 +393,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
@NonNull int[] states) {
log("getDevicesMatchingConnectionStates()");
+ Objects.requireNonNull(states, "states cannot be null");
final IBluetoothLeBroadcastAssistant service = getService();
final List<BluetoothDevice> defaultValue = new ArrayList<BluetoothDevice>();
if (service == null) {
@@ -445,6 +447,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
* @param device Paired bluetooth device
* @param connectionPolicy is the connection policy to set to for this profile
* @return true if connectionPolicy is set, false on error
+ * @throws NullPointerException if <var>device</var> is null
* @hide
*/
@SystemApi
@@ -456,6 +459,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
@ConnectionPolicy int connectionPolicy) {
log("setConnectionPolicy()");
+ Objects.requireNonNull(device, "device cannot be null");
final IBluetoothLeBroadcastAssistant service = getService();
final boolean defaultValue = false;
if (service == null) {
@@ -482,6 +486,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
*
* @param device Bluetooth device
* @return connection policy of the device
+ * @throws NullPointerException if <var>device</var> is null
* @hide
*/
@SystemApi
@@ -492,6 +497,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
})
public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
log("getConnectionPolicy()");
+ Objects.requireNonNull(device, "device cannot be null");
final IBluetoothLeBroadcastAssistant service = getService();
final int defaultValue = BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
if (service == null) {
@@ -518,8 +524,8 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
*
* @param executor an {@link Executor} to execute given callback
* @param callback user implementation of the {@link Callback}
- * @throws NullPointerException if a null executor, or callback is given, or
- * IllegalArgumentException if the same <var>callback<var> is already registered.
+ * @throws NullPointerException if a null executor, or callback is given
+ * @throws IllegalArgumentException if the same <var>callback<var> is already registered
* @hide
*/
@SystemApi
@@ -554,8 +560,8 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
* <p>Callbacks are automatically unregistered when application process goes away.
*
* @param callback user implementation of the {@link Callback}
- * @throws NullPointerException when callback is null or IllegalArgumentException when no
- * callback is registered
+ * @throws NullPointerException when callback is null
+ * @throws IllegalArgumentException when the <var>callback</var> was not registered before
* @hide
*/
@SystemApi
@@ -572,9 +578,10 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
} else if (mBluetoothAdapter.isEnabled()) {
- if (mCallback != null) {
- mCallback.unregister(callback);
+ if (mCallback == null) {
+ throw new IllegalArgumentException("no callback was ever registered");
}
+ mCallback.unregister(callback);
}
}
@@ -605,7 +612,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
*
* @param filters {@link ScanFilter}s for finding exact Broadcast Source, if no filter is
* needed, please provide an empty list instead
- * @throws IllegalArgumentException when <var>filters</var> argument is null
+ * @throws NullPointerException when <var>filters</var> argument is null
* @throws IllegalStateException when no callback is registered
* @hide
*/
@@ -618,8 +625,12 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
})
public void startSearchingForSources(@NonNull List<ScanFilter> filters) {
log("searchForBroadcastSources");
- if (filters == null) {
- throw new IllegalArgumentException("filters can be empty, but not null");
+ Objects.requireNonNull(filters, "filters can be empty, but not null");
+ if (mCallback == null) {
+ throw new IllegalStateException("No callback was ever registered");
+ }
+ if (!mCallback.isAtLeastOneCallbackRegistered()) {
+ throw new IllegalStateException("All callbacks are unregistered");
}
final IBluetoothLeBroadcastAssistant service = getService();
if (service == null) {
@@ -652,6 +663,12 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
})
public void stopSearchingForSources() {
log("stopSearchingForSources:");
+ if (mCallback == null) {
+ throw new IllegalStateException("No callback was ever registered");
+ }
+ if (!mCallback.isAtLeastOneCallbackRegistered()) {
+ throw new IllegalStateException("All callbacks are unregistered");
+ }
final IBluetoothLeBroadcastAssistant service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
@@ -751,7 +768,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
* @param isGroupOp {@code true} if Application wants to perform this operation for all
* coordinated set members throughout this session. Otherwise, caller
* would have to add, modify, and remove individual set members.
- * @throws IllegalArgumentException if <var>sink</var> or <var>source</var> are null
+ * @throws NullPointerException if <var>sink</var> or <var>source</var> is null
* @throws IllegalStateException if callback was not registered
* @hide
*/
@@ -764,6 +781,14 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
public void addSource(@NonNull BluetoothDevice sink,
@NonNull BluetoothLeBroadcastMetadata sourceMetadata, boolean isGroupOp) {
log("addBroadcastSource: " + sourceMetadata + " on " + sink);
+ Objects.requireNonNull(sink, "sink cannot be null");
+ Objects.requireNonNull(sourceMetadata, "sourceMetadata cannot be null");
+ if (mCallback == null) {
+ throw new IllegalStateException("No callback was ever registered");
+ }
+ if (!mCallback.isAtLeastOneCallbackRegistered()) {
+ throw new IllegalStateException("All callbacks are unregistered");
+ }
final IBluetoothLeBroadcastAssistant service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
@@ -818,6 +843,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
* {@link Callback#onSourceAdded(BluetoothDevice, int, int)}
* @param updatedMetadata updated Broadcast Source metadata to be updated on the Broadcast Sink
* @throws IllegalStateException if callback was not registered
+ * @throws NullPointerException if <var>sink</var> or <var>updatedMetadata</var> is null
* @hide
*/
@SystemApi
@@ -829,6 +855,14 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
public void modifySource(@NonNull BluetoothDevice sink, int sourceId,
@NonNull BluetoothLeBroadcastMetadata updatedMetadata) {
log("updateBroadcastSource: " + updatedMetadata + " on " + sink);
+ Objects.requireNonNull(sink, "sink cannot be null");
+ Objects.requireNonNull(updatedMetadata, "updatedMetadata cannot be null");
+ if (mCallback == null) {
+ throw new IllegalStateException("No callback was ever registered");
+ }
+ if (!mCallback.isAtLeastOneCallbackRegistered()) {
+ throw new IllegalStateException("All callbacks are unregistered");
+ }
final IBluetoothLeBroadcastAssistant service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
@@ -862,7 +896,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
* @param sink Broadcast Sink from which a Broadcast Source should be removed
* @param sourceId source ID as delivered in
* {@link Callback#onSourceAdded(BluetoothDevice, int, int)}
- * @throws IllegalArgumentException when the <var>sink</var> is null
+ * @throws NullPointerException when the <var>sink</var> is null
* @throws IllegalStateException if callback was not registered
* @hide
*/
@@ -874,6 +908,13 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
})
public void removeSource(@NonNull BluetoothDevice sink, int sourceId) {
log("removeBroadcastSource: " + sourceId + " from " + sink);
+ Objects.requireNonNull(sink, "sink cannot be null");
+ if (mCallback == null) {
+ throw new IllegalStateException("No callback was ever registered");
+ }
+ if (!mCallback.isAtLeastOneCallbackRegistered()) {
+ throw new IllegalStateException("All callbacks are unregistered");
+ }
final IBluetoothLeBroadcastAssistant service = getService();
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
@@ -894,7 +935,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
* @param sink Broadcast Sink from which to get all Broadcast Sources
* @return the list of Broadcast Receive State {@link BluetoothLeBroadcastReceiveState}
* stored in the Broadcast Sink
- * @throws IllegalArgumentException when <var>sink</var> is null
+ * @throws NullPointerException when <var>sink</var> is null
* @hide
*/
@SystemApi
@@ -906,6 +947,7 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
public @NonNull List<BluetoothLeBroadcastReceiveState> getAllSources(
@NonNull BluetoothDevice sink) {
log("getAllSources()");
+ Objects.requireNonNull(sink, "sink cannot be null");
final IBluetoothLeBroadcastAssistant service = getService();
final List<BluetoothLeBroadcastReceiveState> defaultValue =
new ArrayList<BluetoothLeBroadcastReceiveState>();
@@ -927,11 +969,12 @@ public final class BluetoothLeBroadcastAssistant implements BluetoothProfile, Au
*
* @param sink Broadcast Sink device
* @return maximum number of sources that can be added to this Broadcast Sink
- * @throws IllegalArgumentException when <var>sink</var> is null
+ * @throws NullPointerException when <var>sink</var> is null
* @hide
*/
@SystemApi
public int getMaximumSourceCapacity(@NonNull BluetoothDevice sink) {
+ Objects.requireNonNull(sink, "sink cannot be null");
final IBluetoothLeBroadcastAssistant service = getService();
final int defaultValue = 0;
if (service == null) {
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
index 96e04a9424..aa7ca8ea52 100755
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistantCallback.java
@@ -44,12 +44,13 @@ public class BluetoothLeBroadcastAssistantCallback
* @hide
* @param executor an {@link Executor} to execute given callback
* @param callback user implementation of the {@link BluetoothLeBroadcastAssistant#Callback}
+ * @throws IllegalArgumentException if the same <var>callback<var> is already registered.
*/
public void register(@NonNull Executor executor,
@NonNull BluetoothLeBroadcastAssistant.Callback callback) {
synchronized (this) {
if (mCallbackMap.containsKey(callback)) {
- return;
+ throw new IllegalArgumentException("callback is already registered");
}
mCallbackMap.put(callback, executor);
@@ -58,7 +59,7 @@ public class BluetoothLeBroadcastAssistantCallback
mAdapter.registerCallback(this);
mIsRegistered = true;
} catch (RemoteException e) {
- Log.w(TAG, "Failed to register broaddcast assistant callback");
+ Log.w(TAG, "Failed to register broadcast assistant callback");
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
@@ -68,11 +69,12 @@ public class BluetoothLeBroadcastAssistantCallback
/**
* @hide
* @param callback user implementation of the {@link BluetoothLeBroadcastAssistant#Callback}
+ * @throws IllegalArgumentException if <var>callback</var> was not registered before
*/
public void unregister(@NonNull BluetoothLeBroadcastAssistant.Callback callback) {
synchronized (this) {
if (!mCallbackMap.containsKey(callback)) {
- return;
+ throw new IllegalArgumentException("callback was not registered before");
}
mCallbackMap.remove(callback);
if (mCallbackMap.isEmpty() && mIsRegistered) {
@@ -80,13 +82,25 @@ public class BluetoothLeBroadcastAssistantCallback
mAdapter.unregisterCallback(this);
mIsRegistered = false;
} catch (RemoteException e) {
- Log.w(TAG, "Failed to unregister broaddcast assistant with service");
+ Log.w(TAG, "Failed to unregister callback with service");
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
}
}
+ /**
+ * Check if at least one callback is registered from this App
+ *
+ * @return true if at least one callback is registered
+ * @hide
+ */
+ public boolean isAtLeastOneCallbackRegistered() {
+ synchronized (this) {
+ return !mCallbackMap.isEmpty();
+ }
+ }
+
@Override
public void onSearchStarted(int reason) {
synchronized (this) {
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java b/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java
index 05f7f4a56d..3040af7eb3 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -44,6 +45,22 @@ public final class BluetoothLeBroadcastChannel implements Parcelable {
mCodecMetadata = codecMetadata;
}
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (!(o instanceof BluetoothLeBroadcastChannel)) {
+ return false;
+ }
+ final BluetoothLeBroadcastChannel other = (BluetoothLeBroadcastChannel) o;
+ return mIsSelected == other.isSelected()
+ && mChannelIndex == other.getChannelIndex()
+ && mCodecMetadata.equals(other.getCodecMetadata());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsSelected, mChannelIndex, mCodecMetadata);
+ }
+
/**
* Return true if the channel is selected by Broadcast Assistant for the Broadcast Sink.
*
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java
index c63061a893..b79f31e0bc 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java
@@ -24,6 +24,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -76,6 +77,30 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
mSubgroups = subgroups;
}
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (!(o instanceof BluetoothLeBroadcastMetadata)) {
+ return false;
+ }
+ final BluetoothLeBroadcastMetadata other = (BluetoothLeBroadcastMetadata) o;
+ return mSourceAddressType == other.getSourceAddressType()
+ && mSourceDevice.equals(other.getSourceDevice())
+ && mSourceAdvertisingSid == other.getSourceAdvertisingSid()
+ && mBroadcastId == other.getBroadcastId()
+ && mPaSyncInterval == other.getPaSyncInterval()
+ && mIsEncrypted == other.isEncrypted()
+ && Arrays.equals(mBroadcastCode, other.getBroadcastCode())
+ && mPresentationDelayMicros == other.getPresentationDelayMicros()
+ && mSubgroups.equals(other.getSubgroups());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSourceAddressType, mSourceDevice, mSourceAdvertisingSid,
+ mBroadcastId, mPaSyncInterval, mIsEncrypted, Arrays.hashCode(mBroadcastCode),
+ mPresentationDelayMicros, mSubgroups);
+ }
+
/**
* Get the address type of the Broadcast Source.
*
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java
index b2abe06551..38a747b5d5 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -48,6 +49,23 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {
mChannels = channels;
}
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (!(o instanceof BluetoothLeBroadcastSubgroup)) {
+ return false;
+ }
+ final BluetoothLeBroadcastSubgroup other = (BluetoothLeBroadcastSubgroup) o;
+ return mCodecId == other.getCodecId()
+ && mCodecSpecificConfig.equals(other.getCodecSpecificConfig())
+ && mContentMetadata.equals(other.getContentMetadata())
+ && mChannels.equals(other.getChannels());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mCodecId, mCodecSpecificConfig, mContentMetadata, mChannels);
+ }
+
/**
* Get the codec ID field as defined by the Basic Audio Profile.
*