diff options
382 files changed, 8428 insertions, 8303 deletions
diff --git a/AndroidTestTemplate.xml b/AndroidTestTemplate.xml index 8332422b34..4083baac14 100644 --- a/AndroidTestTemplate.xml +++ b/AndroidTestTemplate.xml @@ -39,7 +39,7 @@ <!-- Only run tests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/android/ChannelSoundingTestApp/app/src/androidTest/java/com/android/bluetooth/channelsoundingtestapp/ExampleInstrumentedTest.java b/android/ChannelSoundingTestApp/app/src/androidTest/java/com/android/bluetooth/channelsoundingtestapp/ExampleInstrumentedTest.java deleted file mode 100644 index 2a73b92d19..0000000000 --- a/android/ChannelSoundingTestApp/app/src/androidTest/java/com/android/bluetooth/channelsoundingtestapp/ExampleInstrumentedTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.bluetooth.channelsoundingtestapp; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.Context; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.platform.app.InstrumentationRegistry; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - assertThat(appContext.getPackageName()) - .isEqualto("com.android.bluetooth.channelsoundingtestapp"); - } -} diff --git a/android/ChannelSoundingTestApp/app/src/test/java/com/android/bluetooth/channelsoundingtestapp/ExampleUnitTest.java b/android/ChannelSoundingTestApp/app/src/test/java/com/android/bluetooth/channelsoundingtestapp/ExampleUnitTest.java deleted file mode 100644 index a3309495cf..0000000000 --- a/android/ChannelSoundingTestApp/app/src/test/java/com/android/bluetooth/channelsoundingtestapp/ExampleUnitTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.bluetooth.channelsoundingtestapp; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> - */ -public class ExampleUnitTest { - - @Test - public void addition_isCorrect() { - assertThat(2 + 2).isEqualTo(4); - } -} diff --git a/android/apishim/Android.bp b/android/apishim/Android.bp index 9d980b2498..7780c014f3 100644 --- a/android/apishim/Android.bp +++ b/android/apishim/Android.bp @@ -23,9 +23,7 @@ java_defaults { "androidx.annotation_annotation", "modules-utils-build", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } diff --git a/android/app/Android.bp b/android/app/Android.bp index db85914522..2da5e5ada9 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -32,9 +32,7 @@ java_library { name: "bluetooth.mapsapi", srcs: ["lib/mapapi/**/*.java"], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", sdk_version: "module_current", lint: { @@ -47,9 +45,7 @@ java_library { srcs: [":framework-mms-shared-srcs"], libs: ["unsupportedappusage"], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", sdk_version: "module_current", lint: { @@ -80,7 +76,7 @@ cc_library_shared { "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/gd", ], - // libbluetooth_jni is the jni lib included in the btservices apex. + // libbluetooth_jni is the jni lib included in the com.android.bt apex. // As this library is inside an APEX the shared_libs that does not // expose stubs are copied inside it. As a result using those as // shared libraries is less interesting as they are not shared, so we link @@ -164,9 +160,7 @@ cc_library_shared { sanitize: { scs: true, }, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } @@ -200,15 +194,12 @@ cc_library { sanitize: { scs: true, }, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } // Bluetooth APK - android_app { name: "Bluetooth", defaults: ["bluetooth_framework_errorprone_rules"], @@ -219,6 +210,7 @@ android_app { ":system-messages-proto-src", "proto/keystore.proto", "src/**/*.java", + "src/**/*.kt", ], proto: { type: "lite", @@ -234,7 +226,6 @@ android_app { jni_uses_platform_apis: true, libs: [ - "app-compat-annotations", "bluetooth_constants_java", "bluetooth_flags_java_lib", "error_prone_annotations", @@ -246,7 +237,6 @@ android_app { "framework-mediaprovider.stubs.module_lib", "framework-statsd.stubs.module_lib", "framework-tethering.stubs.module_lib", - "unsupportedappusage", // Need to link the class at runtime "framework-bluetooth.stubs.module_lib", @@ -338,39 +328,15 @@ android_app { enabled: true, shrink: true, optimize: false, - // TODO(b/289285719): Revisit after resolving mocking issues in testing. - proguard_compatibility: true, proguard_flags_files: ["proguard.flags"], }, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", sdk_version: "module_current", updatable: true, } java_library { - name: "bluetooth.change-ids", - srcs: [ - "src/com/android/bluetooth/ChangeIds.java", - ], - libs: [ - "app-compat-annotations", - ], - apex_available: [ - "com.android.btservices", - ], - min_sdk_version: "Tiramisu", - sdk_version: "module_current", -} - -platform_compat_config { - name: "bluetoothapk-platform-compat-config", - src: ":bluetooth.change-ids", -} - -java_library { name: "bluetooth-proto-enums-java-gen", installable: false, proto: { @@ -379,9 +345,7 @@ java_library { srcs: [ ":srcs_bluetooth_protos", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", sdk_version: "module_current", } diff --git a/android/app/aidl/Android.bp b/android/app/aidl/Android.bp index 0829e0296c..edc1d050f9 100644 --- a/android/app/aidl/Android.bp +++ b/android/app/aidl/Android.bp @@ -17,6 +17,7 @@ filegroup { "android/bluetooth/IBluetoothA2dp.aidl", "android/bluetooth/IBluetoothA2dpSink.aidl", "android/bluetooth/IBluetoothActivityEnergyInfoListener.aidl", + "android/bluetooth/IBluetoothAdvertise.aidl", "android/bluetooth/IBluetoothAvrcpController.aidl", "android/bluetooth/IBluetoothCallback.aidl", "android/bluetooth/IBluetoothConnectionCallback.aidl", @@ -59,6 +60,7 @@ filegroup { "android/bluetooth/IBluetoothSocketManager.aidl", "android/bluetooth/IBluetoothVolumeControl.aidl", "android/bluetooth/IBluetoothVolumeControlCallback.aidl", + "android/bluetooth/IDistanceMeasurement.aidl", "android/bluetooth/IncomingRfcommSocketInfo.aidl", "android/bluetooth/le/IAdvertisingSetCallback.aidl", "android/bluetooth/le/IDistanceMeasurementCallback.aidl", diff --git a/android/app/aidl/android/bluetooth/IBluetooth.aidl b/android/app/aidl/android/bluetooth/IBluetooth.aidl index 158e37823f..9ab583b042 100644 --- a/android/app/aidl/android/bluetooth/IBluetooth.aidl +++ b/android/app/aidl/android/bluetooth/IBluetooth.aidl @@ -344,4 +344,10 @@ interface IBluetooth @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)") boolean isRfcommSocketOffloadSupported(in AttributionSource source); + + @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") + IBinder getBluetoothAdvertise(); + + @JavaPassthrough(annotation="@android.annotation.RequiresNoPermission") + IBinder getDistanceMeasurement(); } diff --git a/android/app/aidl/android/bluetooth/IBluetoothAdvertise.aidl b/android/app/aidl/android/bluetooth/IBluetoothAdvertise.aidl new file mode 100644 index 0000000000..bb7a49daf0 --- /dev/null +++ b/android/app/aidl/android/bluetooth/IBluetoothAdvertise.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.bluetooth.le.AdvertiseSettings; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertisingSetParameters; +import android.bluetooth.le.IAdvertisingSetCallback; +import android.bluetooth.le.IPeriodicAdvertisingCallback; +import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; + +/** + * API for interacting with BLE advertising + * @hide + */ +interface IBluetoothAdvertise { + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)") + void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData, + in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters, + in AdvertiseData periodicData, in int duration, in int maxExtAdvEvents, in int gattServerIf, + in IAdvertisingSetCallback callback, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void stopAdvertisingSet(in IAdvertisingSetCallback callback, in AttributionSource attributionSource); + + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + void getOwnAddress(in int advertiserId, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void setAdvertisingData(in int advertiserId, in AdvertiseData data, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void setScanResponseData(in int advertiserId, in AdvertiseData data, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)") + void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") + void setPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in AttributionSource attributionSource); +} diff --git a/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl b/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl index bfc380f50a..40976dbf00 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl @@ -16,30 +16,12 @@ package android.bluetooth; -import android.app.PendingIntent; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGattService; -import android.bluetooth.le.AdvertiseSettings; -import android.bluetooth.le.AdvertiseData; -import android.bluetooth.le.AdvertisingSetParameters; -import android.bluetooth.le.DistanceMeasurementMethod; -import android.bluetooth.le.DistanceMeasurementParams; -import android.bluetooth.le.IDistanceMeasurementCallback; -import android.bluetooth.le.PeriodicAdvertisingParameters; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.bluetooth.le.ResultStorageDescriptor; -import android.content.AttributionSource; -import android.os.ParcelUuid; -import android.os.WorkSource; - import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; -import android.bluetooth.le.IAdvertisingSetCallback; -import android.bluetooth.le.IPeriodicAdvertisingCallback; -import android.bluetooth.le.IScannerCallback; - +import android.content.AttributionSource; +import android.os.ParcelUuid; /** * API for interacting with BLE / GATT * @hide @@ -48,31 +30,6 @@ interface IBluetoothGatt { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)") - void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData, - in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters, - in AdvertiseData periodicData, in int duration, in int maxExtAdvEvents, in int gattServerIf, - in IAdvertisingSetCallback callback, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void stopAdvertisingSet(in IAdvertisingSetCallback callback, in AttributionSource attributionSource); - - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void getOwnAddress(in int advertiserId, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void enableAdvertisingSet(in int advertiserId, in boolean enable, in int duration, in int maxExtAdvEvents, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void setAdvertisingData(in int advertiserId, in AdvertiseData data, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void setScanResponseData(in int advertiserId, in AdvertiseData data, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_ADVERTISE,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)") - void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)") - void setPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback, boolean eatt_support, in AttributionSource attributionSource); @@ -150,17 +107,4 @@ interface IBluetoothGatt { void disconnectAll(in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true)") int subrateModeRequest(in int clientIf, in BluetoothDevice device, in int subrateMode, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods(in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - void startDistanceMeasurement(in ParcelUuid uuid, in DistanceMeasurementParams params, in IDistanceMeasurementCallback callback, - in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - int stopDistanceMeasurement(in ParcelUuid uuid, in BluetoothDevice device, in int method, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - int getChannelSoundingMaxSupportedSecurityLevel(in BluetoothDevice remoteDevice, in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - int getLocalChannelSoundingMaxSupportedSecurityLevel(in AttributionSource attributionSource); - @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - int[] getChannelSoundingSupportedSecurityLevels(in AttributionSource attributionSource); } diff --git a/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl b/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl new file mode 100644 index 0000000000..78c793a351 --- /dev/null +++ b/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl @@ -0,0 +1,44 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.DistanceMeasurementMethod; +import android.bluetooth.le.DistanceMeasurementParams; +import android.bluetooth.le.IDistanceMeasurementCallback; +import android.content.AttributionSource; +import android.os.ParcelUuid; + +/** + * API for interacting with distance measurement + * @hide + */ +interface IDistanceMeasurement { + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods(in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + void startDistanceMeasurement(in ParcelUuid uuid, in DistanceMeasurementParams params, in IDistanceMeasurementCallback callback, + in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + int stopDistanceMeasurement(in ParcelUuid uuid, in BluetoothDevice device, in int method, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + int getChannelSoundingMaxSupportedSecurityLevel(in BluetoothDevice remoteDevice, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + int getLocalChannelSoundingMaxSupportedSecurityLevel(in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + int[] getChannelSoundingSupportedSecurityLevels(in AttributionSource attributionSource); +} diff --git a/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl b/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl index 35e88a4a68..449b173309 100644 --- a/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl +++ b/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl @@ -20,7 +20,7 @@ package android.bluetooth.le; * @hide */ oneway interface IAdvertisingSetCallback { - void onAdvertisingSetStarted(in IBinder gattBinder, in int advertiserId, in int tx_power, in int status); + void onAdvertisingSetStarted(in IBinder advertiseBinder, in int advertiserId, in int tx_power, in int status); void onOwnAddressRead(in int advertiserId, in int addressType, in String address); void onAdvertisingSetStopped(in int advertiserId); void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status); diff --git a/android/app/change-ids/Android.bp b/android/app/change-ids/Android.bp new file mode 100644 index 0000000000..ab4e853c3f --- /dev/null +++ b/android/app/change-ids/Android.bp @@ -0,0 +1,31 @@ +// Copyright 2025 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +java_library { + name: "bluetooth.change-ids", + srcs: ["com/android/bluetooth/ChangeIds.java"], + libs: ["app-compat-annotations"], + apex_available: ["com.android.bt"], + min_sdk_version: "Tiramisu", + sdk_version: "module_current", +} + +platform_compat_config { + name: "bluetoothapk-platform-compat-config", + src: ":bluetooth.change-ids", +} diff --git a/android/app/src/com/android/bluetooth/ChangeIds.java b/android/app/change-ids/com/android/bluetooth/ChangeIds.java index 4c06486dee..4c06486dee 100644 --- a/android/app/src/com/android/bluetooth/ChangeIds.java +++ b/android/app/change-ids/com/android/bluetooth/ChangeIds.java diff --git a/android/app/proguard.flags b/android/app/proguard.flags index 75da0433f5..80b6c4a32a 100644 --- a/android/app/proguard.flags +++ b/android/app/proguard.flags @@ -7,4 +7,10 @@ -keep class android.support.v4.media.MediaDescriptionCompat { *; } # Required for tests that use Mockito's thenThrow with checked exceptions. --keepattributes Exceptions
\ No newline at end of file +-keepattributes Exceptions + +# Minimal set of keep rules for mocked methods with checked exceptions. +# This can be relaxed to specific packages if that simplifies testing. +# See also https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md#r8-full-mode. +-keepclassmembers,allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification class com.android.bluetooth.BluetoothMethodProxy { public <methods>; } +-keepclassmembers,allowshrinking,allowoptimization,allowobfuscation,allowaccessmodification class com.android.obex.Operation { public <methods>; } diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java index f45fc0b189..e4de73700c 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java @@ -79,6 +79,7 @@ class MediaBrowserWrapper { private final Looper mLooper; private final String mPackageName; private final Handler mRunHandler; + private final String mClassName; private ConnectionState mBrowserConnectionState = ConnectionState.DISCONNECTED; @@ -94,6 +95,7 @@ class MediaBrowserWrapper { Context context, Looper looper, String packageName, String className) { mContext = context; mPackageName = packageName; + mClassName = className; mLooper = looper; mRunHandler = new Handler(mLooper); mWrappedBrowser = @@ -383,4 +385,9 @@ class MediaBrowserWrapper { return mRunHandler; } } + + @Override + public String toString() { + return "Browsable Package & Class Name: " + mPackageName + " " + mClassName + "\n"; + } } diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptor.java b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptor.java index 76daff6a52..1e3be0184a 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptor.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptor.java @@ -87,7 +87,7 @@ public class BipImageDescriptor { * @param encoding The encoding you would like to set as a BIP spec defined string * @return This object so you can continue building */ - public Builder setPropietaryEncoding(String encoding) { + public Builder setProprietaryEncoding(String encoding) { mImageDescriptor.mEncoding = new BipEncoding(BipEncoding.USR_XXX, encoding); return this; } diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java index e4ce96a2fb..53657b16a6 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -3091,6 +3091,13 @@ public class BassClientService extends ProfileService { mCallbacks.notifySourceAddFailed(device, sourceMetadata, statusCode); continue; } + if (!stateMachine.isBassStateReady()) { + Log.d(TAG, "addSource: BASS state not ready, retry later with device: " + device); + synchronized (mPendingSourcesToAdd) { + mPendingSourcesToAdd.add(new AddSourceData(device, sourceMetadata, isGroupOp)); + } + continue; + } if (stateMachine.hasPendingSourceOperation()) { Log.w( TAG, @@ -3730,38 +3737,76 @@ public class BassClientService extends ProfileService { } } - /** Handle device newly connected and its peer device still has active source */ - private void checkAndResumeBroadcast(BluetoothDevice sink) { + /* Handle device Bass state ready and check if assistant should resume broadcast */ + private void handleBassStateReady(BluetoothDevice sink) { + // Check its peer device still has active source Map<Integer, BluetoothLeBroadcastMetadata> entry = mBroadcastMetadataMap.get(sink); - if (entry == null) { - Log.d(TAG, "checkAndResumeBroadcast: no entry for device: " + sink + ", available"); - return; + if (entry != null) { + for (Map.Entry<Integer, BluetoothLeBroadcastMetadata> idMetadataIdPair : + entry.entrySet()) { + BluetoothLeBroadcastMetadata metadata = idMetadataIdPair.getValue(); + if (metadata == null) { + Log.d(TAG, "handleBassStateReady: no metadata available"); + continue; + } + for (BluetoothDevice groupDevice : getTargetDeviceList(sink, true)) { + if (groupDevice.equals(sink)) { + continue; + } + // Check peer device + Optional<BluetoothLeBroadcastReceiveState> receiver = + getOrCreateStateMachine(groupDevice).getAllSources().stream() + .filter(e -> e.getBroadcastId() == metadata.getBroadcastId()) + .findAny(); + if (receiver.isPresent() + && !getAllSources(sink).stream() + .anyMatch( + rs -> + (rs.getBroadcastId() + == receiver.get().getBroadcastId()))) { + Log.d(TAG, "handleBassStateReady: restore the source for device, " + sink); + addSource(sink, metadata, false); + return; + } + } + } + } else { + Log.d(TAG, "handleBassStateReady: no entry for device: " + sink + ", available"); } - for (Map.Entry<Integer, BluetoothLeBroadcastMetadata> idMetadataIdPair : entry.entrySet()) { - BluetoothLeBroadcastMetadata metadata = idMetadataIdPair.getValue(); - if (metadata == null) { - Log.d(TAG, "checkAndResumeBroadcast: no metadata available"); - continue; - } - for (BluetoothDevice groupDevice : getTargetDeviceList(sink, true)) { - if (groupDevice.equals(sink)) { - continue; + // Continue to check if there is pending source to add due to BASS not ready + synchronized (mPendingSourcesToAdd) { + Iterator<AddSourceData> iterator = mPendingSourcesToAdd.iterator(); + while (iterator.hasNext()) { + AddSourceData pendingSourcesToAdd = iterator.next(); + if (pendingSourcesToAdd.mSink.equals(sink)) { + Log.d(TAG, "handleBassStateReady: retry adding source with device, " + sink); + addSource( + pendingSourcesToAdd.mSink, + pendingSourcesToAdd.mSourceMetadata, + pendingSourcesToAdd.mIsGroupOp); + iterator.remove(); + return; } - // Check peer device - Optional<BluetoothLeBroadcastReceiveState> receiver = - getOrCreateStateMachine(groupDevice).getAllSources().stream() - .filter(e -> e.getBroadcastId() == metadata.getBroadcastId()) - .findAny(); - if (receiver.isPresent() - && !getAllSources(sink).stream() - .anyMatch( - rs -> - (rs.getBroadcastId() - == receiver.get().getBroadcastId()))) { - Log.d(TAG, "checkAndResumeBroadcast: restore the source for device: " + sink); - addSource(sink, metadata, false); + } + } + } + + /* Handle device Bass state setup failed */ + private void handleBassStateSetupFailed(BluetoothDevice sink) { + // Check if there is pending source to add due to BASS not ready + synchronized (mPendingSourcesToAdd) { + Iterator<AddSourceData> iterator = mPendingSourcesToAdd.iterator(); + while (iterator.hasNext()) { + AddSourceData pendingSourcesToAdd = iterator.next(); + if (pendingSourcesToAdd.mSink.equals(sink)) { + mCallbacks.notifySourceAddFailed( + pendingSourcesToAdd.mSink, + pendingSourcesToAdd.mSourceMetadata, + BluetoothStatusCodes.ERROR_REMOTE_NOT_ENOUGH_RESOURCES); + iterator.remove(); + return; } } } @@ -4054,13 +4099,11 @@ public class BassClientService extends ProfileService { } /** Check if any sink receivers are receiving broadcast stream */ - public boolean isAnyReceiverReceivingBroadcast(List<BluetoothDevice> devices) { + public boolean isAnyReceiverActive(List<BluetoothDevice> devices) { for (BluetoothDevice device : devices) { for (BluetoothLeBroadcastReceiveState receiveState : getAllSources(device)) { - for (int i = 0; i < receiveState.getNumSubgroups(); i++) { - if (isSyncedToBroadcastStream(receiveState.getBisSyncState().get(i))) { - return true; - } + if (isReceiverActive(receiveState)) { + return true; } } } @@ -4193,8 +4236,8 @@ public class BassClientService extends ProfileService { } private boolean isSyncedToBroadcastStream(Long syncState) { - return syncState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS - && syncState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG; + return syncState != BassConstants.BCAST_RCVR_STATE_BIS_SYNC_NOT_SYNC_TO_BIS + && syncState != BassConstants.BCAST_RCVR_STATE_BIS_SYNC_FAILED_SYNC_TO_BIG; } /** Handle broadcast state changed */ @@ -4237,6 +4280,7 @@ public class BassClientService extends ProfileService { private static final int MSG_RECEIVESTATE_CHANGED = 12; private static final int MSG_SOURCE_LOST = 13; private static final int MSG_BASS_STATE_READY = 14; + private static final int MSG_BASS_STATE_SETUP_FAILED = 15; @GuardedBy("mCallbacksList") private final RemoteCallbackList<IBluetoothLeBroadcastAssistantCallback> mCallbacksList = @@ -4300,7 +4344,12 @@ public class BassClientService extends ProfileService { switch (msg.what) { case MSG_BASS_STATE_READY: sink = (BluetoothDevice) msg.obj; - sService.checkAndResumeBroadcast(sink); + sService.handleBassStateReady(sink); + isMsgHandled = true; + break; + case MSG_BASS_STATE_SETUP_FAILED: + sink = (BluetoothDevice) msg.obj; + sService.handleBassStateSetupFailed(sink); isMsgHandled = true; break; default: @@ -4579,6 +4628,11 @@ public class BassClientService extends ProfileService { sEventLogger.logd(TAG, "notifyBassStateReady: sink: " + sink); obtainMessage(MSG_BASS_STATE_READY, sink).sendToTarget(); } + + void notifyBassStateSetupFailed(BluetoothDevice sink) { + sEventLogger.logd(TAG, "notifyBassStateSetupFailed: sink: " + sink); + obtainMessage(MSG_BASS_STATE_SETUP_FAILED, sink).sendToTarget(); + } } @Override diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index efdc0dcae7..8ce618c9b4 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -155,6 +155,7 @@ class BassClientStateMachine extends StateMachine { @VisibleForTesting BluetoothGattCharacteristic mBroadcastScanControlPoint; private final Map<Integer, Boolean> mFirstTimeBisDiscoveryMap; private int mPASyncRetryCounter = 0; + private boolean mBassStateReady = false; @VisibleForTesting int mNumOfBroadcastReceiverStates = 0; int mNumOfReadyBroadcastReceiverStates = 0; @VisibleForTesting int mPendingOperation = -1; @@ -939,15 +940,15 @@ class BassClientStateMachine extends StateMachine { // Check Bis state for (int i = 0; i < recvState.getNumSubgroups(); i++) { Long bisState = recvState.getBisSyncState().get(i); - if (bisState != BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG - && bisState != BassConstants.BIS_SYNC_NOT_SYNC_TO_BIS) { + if (bisState != BassConstants.BCAST_RCVR_STATE_BIS_SYNC_FAILED_SYNC_TO_BIG + && bisState != BassConstants.BCAST_RCVR_STATE_BIS_SYNC_NOT_SYNC_TO_BIS) { // Any bis synced, update status and break syncStats.updateBisSyncedTime(SystemClock.elapsedRealtime()); syncStats.updateSyncStatus( BluetoothStatsLog .BROADCAST_AUDIO_SYNC_REPORTED__SYNC_STATUS__SYNC_STATUS_AUDIO_SYNC_SUCCESS); break; - } else if (bisState == BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG) { + } else if (bisState == BassConstants.BCAST_RCVR_STATE_BIS_SYNC_FAILED_SYNC_TO_BIG) { logBroadcastSyncStatsWithStatus( broadcastId, BluetoothStatsLog @@ -1177,6 +1178,7 @@ class BassClientStateMachine extends StateMachine { if (leaudioBroadcastResyncHelper()) { // Notify service BASS state ready for operations mService.getCallbacks().notifyBassStateReady(mDevice); + mBassStateReady = true; } } else { log("Updated receiver state: " + recvState); @@ -1533,6 +1535,7 @@ class BassClientStateMachine extends StateMachine { + status + "mBluetoothGatt" + mBluetoothGatt); + mService.getCallbacks().notifyBassStateSetupFailed(mDevice); } } else { log("remote initiated callback"); @@ -1560,6 +1563,7 @@ class BassClientStateMachine extends StateMachine { if (mNumOfReadyBroadcastReceiverStates == mNumOfBroadcastReceiverStates) { // Notify service BASS state ready for operations mService.getCallbacks().notifyBassStateReady(mDevice); + mBassStateReady = true; } } else { processBroadcastReceiverStateObsolete( @@ -1604,6 +1608,9 @@ class BassClientStateMachine extends StateMachine { if (status == BluetoothGatt.GATT_SUCCESS) { Log.d(TAG, "mtu: " + mtu); mMaxSingleAttributeWriteValueLen = mtu - ATT_WRITE_CMD_HDR_LEN; + } else { + Log.w(TAG, "onMtuChanged failed: " + status); + mService.getCallbacks().notifyBassStateSetupFailed(mDevice); } } @@ -1875,6 +1882,7 @@ class BassClientStateMachine extends StateMachine { } mPendingOperation = -1; mPendingMetadata = null; + mBassStateReady = false; mCurrentMetadata.clear(); mPendingRemove.clear(); } @@ -2049,15 +2057,16 @@ class BassClientStateMachine extends StateMachine { } } - private static int getBisSyncFromChannelPreference(List<BluetoothLeBroadcastChannel> channels) { - int bisSync = 0; + private static long getBisSyncFromChannelPreference( + List<BluetoothLeBroadcastChannel> channels) { + long bisSync = 0L; for (BluetoothLeBroadcastChannel channel : channels) { if (channel.isSelected()) { if (channel.getChannelIndex() == 0) { Log.e(TAG, "getBisSyncFromChannelPreference: invalid channel index=0"); continue; } - bisSync |= 1 << (channel.getChannelIndex() - 1); + bisSync |= 1L << (channel.getChannelIndex() - 1); } } @@ -2106,14 +2115,14 @@ class BassClientStateMachine extends StateMachine { for (BluetoothLeBroadcastSubgroup subGroup : subGroups) { // BIS_Sync - int bisSync = getBisSyncFromChannelPreference(subGroup.getChannels()); - if (bisSync == 0) { - bisSync = 0xFFFFFFFF; + long bisSync = getBisSyncFromChannelPreference(subGroup.getChannels()); + if (bisSync == BassConstants.BIS_SYNC_DO_NOT_SYNC_TO_BIS) { + bisSync = BassConstants.BIS_SYNC_NO_PREFERENCE; } - stream.write(bisSync & 0x00000000000000FF); - stream.write((bisSync & 0x000000000000FF00) >>> 8); - stream.write((bisSync & 0x0000000000FF0000) >>> 16); - stream.write((bisSync & 0x00000000FF000000) >>> 24); + stream.write((byte) (bisSync & 0x00000000000000FFL)); + stream.write((byte) ((bisSync & 0x000000000000FF00L) >>> 8)); + stream.write((byte) ((bisSync & 0x0000000000FF0000L) >>> 16)); + stream.write((byte) ((bisSync & 0x00000000FF000000L) >>> 24)); // Metadata_Length BluetoothLeAudioContentMetadata metadata = subGroup.getContentMetadata(); @@ -2162,28 +2171,41 @@ class BassClientStateMachine extends StateMachine { res[offset++] = (byte) numSubGroups; for (int i = 0; i < numSubGroups; i++) { - int bisIndexValue = 0xFFFFFFFF; + long bisIndexValue = BassConstants.BIS_SYNC_NO_PREFERENCE; + long currentBisIndexValue = BassConstants.BIS_SYNC_NO_PREFERENCE; + if (i < existingState.getBisSyncState().size()) { + currentBisIndexValue = existingState.getBisSyncState().get(i); + } + if (paSync == BassConstants.PA_SYNC_DO_NOT_SYNC) { - bisIndexValue = 0; - } else if (metaData != null - && (paSync == BassConstants.PA_SYNC_PAST_AVAILABLE - || paSync == BassConstants.PA_SYNC_PAST_NOT_AVAILABLE)) { + bisIndexValue = BassConstants.BIS_SYNC_DO_NOT_SYNC_TO_BIS; + } else if (metaData != null) { bisIndexValue = getBisSyncFromChannelPreference( metaData.getSubgroups().get(i).getChannels()); - // Let sink decide to which BIS sync if there is no channel preference - if (bisIndexValue == 0) { - bisIndexValue = 0xFFFFFFFF; + // If updating metadata with paSync INVALID_PA_SYNC_VALUE + // Use bisIndexValue parsed from metadata channels + if (paSync == BassConstants.PA_SYNC_PAST_AVAILABLE + || paSync == BassConstants.PA_SYNC_PAST_NOT_AVAILABLE) { + // Let sink decide to which BIS sync if there is no channel preference + if (bisIndexValue == BassConstants.BIS_SYNC_DO_NOT_SYNC_TO_BIS) { + bisIndexValue = BassConstants.BIS_SYNC_NO_PREFERENCE; + } } - } else if (i < existingState.getBisSyncState().size()) { - bisIndexValue = existingState.getBisSyncState().get(i).intValue(); + } else { + // Keep using BIS index from remote receive state + bisIndexValue = currentBisIndexValue; } - log("UPDATE_BCAST_SOURCE: bisIndexValue : " + bisIndexValue); + log( + "UPDATE_BCAST_SOURCE: bisIndexValue from: " + + currentBisIndexValue + + " to: " + + bisIndexValue); // BIS_Sync - res[offset++] = (byte) (bisIndexValue & 0x00000000000000FF); - res[offset++] = (byte) ((bisIndexValue & 0x000000000000FF00) >>> 8); - res[offset++] = (byte) ((bisIndexValue & 0x0000000000FF0000) >>> 16); - res[offset++] = (byte) ((bisIndexValue & 0x00000000FF000000) >>> 24); + res[offset++] = (byte) (bisIndexValue & 0x00000000000000FFL); + res[offset++] = (byte) ((bisIndexValue & 0x000000000000FF00L) >>> 8); + res[offset++] = (byte) ((bisIndexValue & 0x0000000000FF0000L) >>> 16); + res[offset++] = (byte) ((bisIndexValue & 0x00000000FF000000L) >>> 24); // Metadata_Length; On Modify source, don't update any Metadata res[offset++] = 0; } @@ -2863,6 +2885,10 @@ class BassClientStateMachine extends StateMachine { return mNumOfBroadcastReceiverStates; } + boolean isBassStateReady() { + return mBassStateReady; + } + BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) { return mCurrentMetadata.getOrDefault(sourceId, null); } diff --git a/android/app/src/com/android/bluetooth/bass_client/BassConstants.java b/android/app/src/com/android/bluetooth/bass_client/BassConstants.java index 981f4b6287..5efd2d4185 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassConstants.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassConstants.java @@ -62,6 +62,9 @@ public class BassConstants { public static final int BCAST_RCVR_STATE_BADCODE_START_IDX = 14; public static final int BCAST_RCVR_STATE_BADCODE_SIZE = 16; public static final int BCAST_RCVR_STATE_BIS_SYNC_SIZE = 4; + // BIS_Sync State value + public static final long BCAST_RCVR_STATE_BIS_SYNC_NOT_SYNC_TO_BIS = 0x00000000L; + public static final long BCAST_RCVR_STATE_BIS_SYNC_FAILED_SYNC_TO_BIG = 0xFFFFFFFFL; // 30 secs time out for all gatt writes public static final int GATT_TXN_TIMEOUT_MS = 30000; public static final int SOURCE_OPERATION_TIMEOUT_MS = 3000; @@ -75,11 +78,11 @@ public class BassConstants { public static final int BCAST_NAME_AD_TYPE = 0x30; public static final int BCAST_NAME_LEN_MIN = 4; public static final int BCAST_NAME_LEN_MAX = 32; - // PA_Sync parameter value + // PA_Sync parameter value in BASS operations public static final int PA_SYNC_DO_NOT_SYNC = 0x00; public static final int PA_SYNC_PAST_AVAILABLE = 0x01; public static final int PA_SYNC_PAST_NOT_AVAILABLE = 0x02; - // BIS_Sync parameter value - public static final long BIS_SYNC_NOT_SYNC_TO_BIS = 0x00000000L; - public static final long BIS_SYNC_FAILED_SYNC_TO_BIG = 0xFFFFFFFFL; + // BIS_Sync parameter value in BASS operations + public static final long BIS_SYNC_DO_NOT_SYNC_TO_BIS = 0x00000000L; + public static final long BIS_SYNC_NO_PREFERENCE = 0xFFFFFFFFL; } diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java index 6fb1169a9e..d84093f66c 100644 --- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java @@ -867,9 +867,6 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac @Override public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) { Log.d(TAG, "onAudioDevicesRemoved"); - if (!Flags.admFallbackWhenWiredAudioDisconnected()) { - return; - } if (!Arrays.stream(removedDevices) .anyMatch(AudioManagerAudioDeviceCallback::isWiredAudioHeadset)) { return; @@ -1236,15 +1233,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac if (Objects.equals(a2dpFallbackDevice, device)) { Log.d(TAG, "Found an A2DP fallback device: " + device); setA2dpActiveDevice(device); - if (Flags.admAlwaysFallbackToAvailableDevice()) { - setHfpActiveDevice(headsetFallbackDevice); - } else { - if (Objects.equals(headsetFallbackDevice, device)) { - setHfpActiveDevice(device); - } else { - setHfpActiveDevice(null); - } - } + setHfpActiveDevice(headsetFallbackDevice); /* If dual mode is enabled, LEA will be made active once all supported classic audio profiles are made active for the device. */ if (!Utils.isDualModeAudioEnabled()) { @@ -1275,15 +1264,7 @@ public class ActiveDeviceManager implements AdapterService.BluetoothStateCallbac if (Objects.equals(headsetFallbackDevice, device)) { Log.d(TAG, "Found a HFP fallback device: " + device); setHfpActiveDevice(device); - if (Flags.admAlwaysFallbackToAvailableDevice()) { - setA2dpActiveDevice(a2dpFallbackDevice); - } else { - if (Objects.equals(a2dpFallbackDevice, device)) { - setA2dpActiveDevice(a2dpFallbackDevice); - } else { - setA2dpActiveDevice(null, true); - } - } + setA2dpActiveDevice(a2dpFallbackDevice); if (!Utils.isDualModeAudioEnabled()) { setLeAudioActiveDevice(null, true); } diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 081c0b57c9..fe9cca3409 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -4179,7 +4179,7 @@ public class AdapterService extends Service { Set<Integer> eventCodesSet = Arrays.stream(eventCodes).boxed().collect(Collectors.toSet()); if (eventCodesSet.stream() - .anyMatch((n) -> (n < 0) || (n >= 0x50 && n < 0x60) || (n > 0xff))) { + .anyMatch((n) -> (n < 0) || (n >= 0x52 && n < 0x60) || (n > 0xff))) { throw new IllegalArgumentException("invalid vendor-specific event code"); } @@ -4410,6 +4410,18 @@ public class AdapterService extends Service { service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); return service.isRfcommSocketOffloadSupported(); } + + @Override + public IBinder getBluetoothAdvertise() { + AdapterService service = getService(); + return service == null ? null : service.getBluetoothAdvertise(); + } + + @Override + public IBinder getDistanceMeasurement() { + AdapterService service = getService(); + return service == null ? null : service.getDistanceMeasurement(); + } } /** @@ -6147,6 +6159,16 @@ public class AdapterService extends Service { } } + @Nullable + IBinder getBluetoothAdvertise() { + return mGattService == null ? null : mGattService.getBluetoothAdvertise(); + } + + @Nullable + IBinder getDistanceMeasurement() { + return mGattService == null ? null : mGattService.getDistanceMeasurement(); + } + @RequiresPermission(BLUETOOTH_CONNECT) void unregAllGattClient(AttributionSource source) { if (mGattService != null) { @@ -6226,10 +6248,9 @@ public class AdapterService extends Service { Log.w(TAG, "GATT Service is not running!"); return; } - if (Flags.scanManagerRefactor()) { - mScanController.notifyProfileConnectionStateChange(profile, fromState, toState); - } else { - mGattService.notifyProfileConnectionStateChange(profile, fromState, toState); + ScanController controller = getBluetoothScanController(); + if (controller != null) { + controller.notifyProfileConnectionStateChange(profile, fromState, toState); } } diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index 4660edf16b..f0bad17e64 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -1405,25 +1405,23 @@ public class RemoteDevices { } private void removeAddressMapping(String address) { - if (Flags.temporaryPairingDeviceProperties()) { - DeviceProperties deviceProperties = mDevices.get(address); - if (deviceProperties != null) { - String pseudoAddress = mDualDevicesMap.get(address); - if (pseudoAddress != null) { - deviceProperties = mDevices.get(pseudoAddress); - } + DeviceProperties deviceProperties = mDevices.get(address); + if (deviceProperties != null) { + String pseudoAddress = mDualDevicesMap.get(address); + if (pseudoAddress != null) { + deviceProperties = mDevices.get(pseudoAddress); } + } - if (deviceProperties != null) { - int leConnectionHandle = - deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_LE); - int bredrConnectionHandle = - deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_BREDR); - if (leConnectionHandle != BluetoothDevice.ERROR - || bredrConnectionHandle != BluetoothDevice.ERROR) { - // Device still connected, wait for disconnection to remove the properties - return; - } + if (deviceProperties != null) { + int leConnectionHandle = + deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_LE); + int bredrConnectionHandle = + deviceProperties.getConnectionHandle(BluetoothDevice.TRANSPORT_BREDR); + if (leConnectionHandle != BluetoothDevice.ERROR + || bredrConnectionHandle != BluetoothDevice.ERROR) { + // Device still connected, wait for disconnection to remove the properties + return; } } diff --git a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java index 7d1ec712b1..d5ec6d3055 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java @@ -201,12 +201,28 @@ public class DatabaseManager { void bondStateChanged(BluetoothDevice device, int state) { synchronized (mMetadataCache) { String address = device.getAddress(); - if (state != BluetoothDevice.BOND_NONE) { + if (!Flags.createMetadataAfterBonding()) { + if (state != BluetoothDevice.BOND_NONE) { + if (mMetadataCache.containsKey(address)) { + return; + } + createMetadata(address, false); + } else { + Metadata metadata = mMetadataCache.get(address); + if (metadata != null) { + mMetadataCache.remove(address); + deleteDatabase(metadata); + } + } + return; + } + + if (state == BluetoothDevice.BOND_BONDED) { if (mMetadataCache.containsKey(address)) { return; } createMetadata(address, false); - } else { + } else if (state == BluetoothDevice.BOND_NONE) { Metadata metadata = mMetadataCache.get(address); if (metadata != null) { mMetadataCache.remove(address); diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.java new file mode 100644 index 0000000000..9e4d281bda --- /dev/null +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.java @@ -0,0 +1,197 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.gatt; + +import static android.Manifest.permission.BLUETOOTH_ADVERTISE; +import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; + +import static java.util.Objects.requireNonNull; + +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.bluetooth.IBluetoothAdvertise; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertisingSetParameters; +import android.bluetooth.le.IAdvertisingSetCallback; +import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; +import android.content.Context; + +import com.android.bluetooth.Utils; + +class AdvertiseBinder extends IBluetoothAdvertise.Stub { + private final Context mContext; + private final AdvertiseManager mAdvertiseManager; + private volatile boolean mIsAvailable = true; + + AdvertiseBinder(Context context, AdvertiseManager manager) { + mContext = context; + mAdvertiseManager = manager; + } + + void cleanup() { + mIsAvailable = false; + } + + @RequiresPermission(BLUETOOTH_ADVERTISE) + @Nullable + private AdvertiseManager getManager(AttributionSource source) { + requireNonNull(source); + if (!Utils.checkAdvertisePermissionForDataDelivery( + mContext, source, "AdvertiseManager startAdvertisingSet")) { + return null; + } + return mIsAvailable ? mAdvertiseManager : null; + } + + @Override + public void startAdvertisingSet( + AdvertisingSetParameters parameters, + @Nullable AdvertiseData advertiseData, + @Nullable AdvertiseData scanResponse, + @Nullable PeriodicAdvertisingParameters periodicParameters, + @Nullable AdvertiseData periodicData, + int duration, + int maxExtAdvEvents, + int serverIf, + IAdvertisingSetCallback callback, + AttributionSource source) { + requireNonNull(parameters); + requireNonNull(callback); + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + if (parameters.getOwnAddressType() != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT + || serverIf != 0 + || parameters.isDirected()) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + } + manager.startAdvertisingSet( + parameters, + advertiseData, + scanResponse, + periodicParameters, + periodicData, + duration, + maxExtAdvEvents, + serverIf, + callback, + source); + } + + @Override + public void stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource source) { + requireNonNull(callback); + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.stopAdvertisingSet(callback); + } + + @Override + public void getOwnAddress(int advertiserId, AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + manager.getOwnAddress(advertiserId); + } + + @Override + public void enableAdvertisingSet( + int advertiserId, + boolean enable, + int duration, + int maxExtAdvEvents, + AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); + } + + @Override + public void setAdvertisingData( + int advertiserId, @Nullable AdvertiseData data, AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.setAdvertisingData(advertiserId, data); + } + + @Override + public void setScanResponseData( + int advertiserId, @Nullable AdvertiseData data, AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.setScanResponseData(advertiserId, data); + } + + @Override + public void setAdvertisingParameters( + int advertiserId, AdvertisingSetParameters parameters, AttributionSource source) { + requireNonNull(parameters); + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + if (parameters.getOwnAddressType() != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT + || parameters.isDirected()) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + } + manager.setAdvertisingParameters(advertiserId, parameters); + } + + @Override + public void setPeriodicAdvertisingParameters( + int advertiserId, + @Nullable PeriodicAdvertisingParameters parameters, + AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.setPeriodicAdvertisingParameters(advertiserId, parameters); + } + + @Override + public void setPeriodicAdvertisingData( + int advertiserId, @Nullable AdvertiseData data, AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.setPeriodicAdvertisingData(advertiserId, data); + } + + @Override + public void setPeriodicAdvertisingEnable( + int advertiserId, boolean enable, AttributionSource source) { + AdvertiseManager manager = getManager(source); + if (manager == null) { + return; + } + manager.setPeriodicAdvertisingEnable(advertiserId, enable); + } +} diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java index f3ccb8a9c1..7e89f99055 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java @@ -47,6 +47,7 @@ public class AdvertiseManager { private final GattService mService; private final AdvertiseManagerNativeInterface mNativeInterface; + private final AdvertiseBinder mAdvertiseBinder; private final AdvertiserMap mAdvertiserMap; @GuardedBy("itself") @@ -74,6 +75,7 @@ public class AdvertiseManager { HandlerThread thread = new HandlerThread("BluetoothAdvertiseManager"); thread.start(); mHandler = new Handler(thread.getLooper()); + mAdvertiseBinder = new AdvertiseBinder(service, this); } // TODO(b/327849650): We shouldn't need this, it should be safe to do in the cleanup method. But @@ -84,6 +86,7 @@ public class AdvertiseManager { void cleanup() { Log.d(TAG, "cleanup()"); + mAdvertiseBinder.cleanup(); mNativeInterface.cleanup(); synchronized (mAdvertisers) { mAdvertisers.clear(); @@ -105,6 +108,10 @@ public class AdvertiseManager { mAdvertiserMap.dump(sb); } + AdvertiseBinder getBinder() { + return mAdvertiseBinder; + } + static class AdvertiserInfo { /* When id is negative, the registration is ongoing. When the registration finishes, id * becomes equal to advertiser_id */ @@ -200,8 +207,7 @@ public class AdvertiseManager { mAdvertiserMap.removeAppAdvertiseStats(regId); } - IBinder gattBinder = mService.getBinder(); - callback.onAdvertisingSetStarted(gattBinder, advertiserId, txPower, status); + callback.onAdvertisingSetStarted(mAdvertiseBinder, advertiserId, txPower, status); } void onAdvertisingEnabled(int advertiserId, boolean enable, int status) throws Exception { @@ -255,9 +261,11 @@ public class AdvertiseManager { != AdvertisingSetParameters.ADDRESS_TYPE_RANDOM_NON_RESOLVABLE) { Log.w(TAG, "Cannot advertise an isolated GATT server using a resolvable address"); try { - IBinder gattBinder = mService.getBinder(); callback.onAdvertisingSetStarted( - gattBinder, 0x00, 0x00, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); + mAdvertiseBinder, + 0x00, + 0x00, + AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); } catch (RemoteException exception) { Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); } @@ -321,9 +329,11 @@ public class AdvertiseManager { } catch (IllegalArgumentException e) { try { binder.unlinkToDeath(deathRecipient, 0); - IBinder gattBinder = mService.getBinder(); callback.onAdvertisingSetStarted( - gattBinder, 0x00, 0x00, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); + mAdvertiseBinder, + 0x00, + 0x00, + AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); } catch (RemoteException exception) { Log.e(TAG, "Failed to callback:" + Log.getStackTraceString(exception)); } @@ -603,4 +613,5 @@ public class AdvertiseManager { stats.onPeriodicAdvertiseEnabled(enable); } } + } diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.java new file mode 100644 index 0000000000..3a23b6899d --- /dev/null +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.java @@ -0,0 +1,145 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.gatt; + +import static android.Manifest.permission.BLUETOOTH_CONNECT; +import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; + +import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; + +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothStatusCodes; +import android.bluetooth.IDistanceMeasurement; +import android.bluetooth.le.ChannelSoundingParams; +import android.bluetooth.le.DistanceMeasurementMethod; +import android.bluetooth.le.DistanceMeasurementParams; +import android.bluetooth.le.IDistanceMeasurementCallback; +import android.content.AttributionSource; +import android.content.Context; +import android.os.ParcelUuid; + +import com.android.bluetooth.Utils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class DistanceMeasurementBinder extends IDistanceMeasurement.Stub { + private static final String TAG = DistanceMeasurementBinder.class.getSimpleName(); + private final Context mContext; + private final DistanceMeasurementManager mDistanceMeasurementManager; + private volatile boolean mIsAvailable = true; + + DistanceMeasurementBinder(Context context, DistanceMeasurementManager manager) { + mContext = context; + mDistanceMeasurementManager = manager; + } + + void cleanup() { + mIsAvailable = false; + } + + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) + @Nullable + private DistanceMeasurementManager getManager(AttributionSource source, String method) { + if (!mIsAvailable + || !callerIsSystemOrActiveOrManagedUser( + mContext, TAG, "DistanceMeasurement " + method) + || !Utils.checkConnectPermissionForDataDelivery( + mContext, source, "DistanceMeasurement " + method)) { + return null; + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return mDistanceMeasurementManager; + } + + @Override + public List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods( + AttributionSource source) { + DistanceMeasurementManager manager = + getManager(source, "getSupportedDistanceMeasurementMethods"); + if (manager == null) { + return Collections.emptyList(); + } + return Arrays.asList(manager.getSupportedDistanceMeasurementMethods()); + } + + @Override + public void startDistanceMeasurement( + ParcelUuid uuid, + DistanceMeasurementParams distanceMeasurementParams, + IDistanceMeasurementCallback callback, + AttributionSource source) { + DistanceMeasurementManager manager = getManager(source, "startDistanceMeasurement"); + if (manager == null) { + return; + } + manager.startDistanceMeasurement(uuid.getUuid(), distanceMeasurementParams, callback); + } + + @Override + public int stopDistanceMeasurement( + ParcelUuid uuid, BluetoothDevice device, int method, AttributionSource source) { + if (!mIsAvailable) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } else if (!callerIsSystemOrActiveOrManagedUser(mContext, TAG, "stopDistanceMeasurement")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } else if (!Utils.checkConnectPermissionForDataDelivery( + mContext, source, "DistanceMeasurement stopDistanceMeasurement")) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return mDistanceMeasurementManager.stopDistanceMeasurement( + uuid.getUuid(), device, method, false); + } + + @Override + public int getChannelSoundingMaxSupportedSecurityLevel( + BluetoothDevice remoteDevice, AttributionSource source) { + DistanceMeasurementManager manager = + getManager(source, "getChannelSoundingMaxSupportedSecurityLevel"); + if (manager == null) { + return ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN; + } + return manager.getChannelSoundingMaxSupportedSecurityLevel(remoteDevice); + } + + @Override + public int getLocalChannelSoundingMaxSupportedSecurityLevel(AttributionSource source) { + DistanceMeasurementManager manager = + getManager(source, "getLocalChannelSoundingMaxSupportedSecurityLevel"); + if (manager == null) { + return ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN; + } + return manager.getLocalChannelSoundingMaxSupportedSecurityLevel(); + } + + @Override + public int[] getChannelSoundingSupportedSecurityLevels(AttributionSource source) { + DistanceMeasurementManager manager = + getManager(source, "getChannelSoundingSupportedSecurityLevels"); + + if (manager == null) { + return new int[0]; + } + return manager.getChannelSoundingSupportedSecurityLevels().stream() + .mapToInt(i -> i) + .toArray(); + } +} diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java index 65e401bd97..bba24e3e9a 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java @@ -54,13 +54,16 @@ public class DistanceMeasurementManager { private final AdapterService mAdapterService; private final HandlerThread mHandlerThread; - DistanceMeasurementNativeInterface mDistanceMeasurementNativeInterface; + private final DistanceMeasurementNativeInterface mDistanceMeasurementNativeInterface; + private final DistanceMeasurementBinder mDistanceMeasurementBinder; private final ConcurrentHashMap<String, CopyOnWriteArraySet<DistanceMeasurementTracker>> mRssiTrackers = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, CopyOnWriteArraySet<DistanceMeasurementTracker>> mCsTrackers = new ConcurrentHashMap<>(); private final boolean mHasChannelSoundingFeature; + private volatile boolean mIsTurnedOff = false; + /** Constructor of {@link DistanceMeasurementManager}. */ DistanceMeasurementManager(AdapterService adapterService) { mAdapterService = adapterService; @@ -70,6 +73,7 @@ public class DistanceMeasurementManager { mHandlerThread.start(); mDistanceMeasurementNativeInterface = DistanceMeasurementNativeInterface.getInstance(); mDistanceMeasurementNativeInterface.init(this); + mDistanceMeasurementBinder = new DistanceMeasurementBinder(adapterService, this); if (Flags.channelSounding25q2Apis()) { mHasChannelSoundingFeature = adapterService @@ -81,7 +85,26 @@ public class DistanceMeasurementManager { } void cleanup() { + mIsTurnedOff = true; + mDistanceMeasurementBinder.cleanup(); mDistanceMeasurementNativeInterface.cleanup(); + Log.d(TAG, "stop all sessions as BT is off"); + for (String addressForCs : mCsTrackers.keySet()) { + onDistanceMeasurementStopped( + addressForCs, + BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, + DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); + } + for (String addressForRssi : mRssiTrackers.keySet()) { + onDistanceMeasurementStopped( + addressForRssi, + BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, + DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); + } + } + + DistanceMeasurementBinder getBinder() { + return mDistanceMeasurementBinder; } DistanceMeasurementMethod[] getSupportedDistanceMeasurementMethods() { @@ -102,6 +125,12 @@ public class DistanceMeasurementManager { void startDistanceMeasurement( UUID uuid, DistanceMeasurementParams params, IDistanceMeasurementCallback callback) { + if (mIsTurnedOff) { + Log.d(TAG, "BT is turned off, no new request is allowed."); + invokeStartFail( + callback, params.getDevice(), BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED); + return; + } Log.i( TAG, "startDistanceMeasurement:" @@ -538,4 +567,5 @@ public class DistanceMeasurementManager { private static void logd(String msg) { Log.d(TAG, msg); } + } diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 2927132986..99642e5bcf 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -16,7 +16,6 @@ package com.android.bluetooth.gatt; -import static android.Manifest.permission.BLUETOOTH_ADVERTISE; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; @@ -43,14 +42,6 @@ import android.bluetooth.BluetoothUtils; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; -import android.bluetooth.le.AdvertiseData; -import android.bluetooth.le.AdvertisingSetParameters; -import android.bluetooth.le.ChannelSoundingParams; -import android.bluetooth.le.DistanceMeasurementMethod; -import android.bluetooth.le.DistanceMeasurementParams; -import android.bluetooth.le.IAdvertisingSetCallback; -import android.bluetooth.le.IDistanceMeasurementCallback; -import android.bluetooth.le.PeriodicAdvertisingParameters; import android.companion.CompanionDeviceManager; import android.content.AttributionSource; import android.content.pm.PackageManager; @@ -284,13 +275,6 @@ public class GattService extends ProfileService { return restrictedHandles != null && restrictedHandles.contains(handle); } - /** Notify Scan manager of bluetooth profile connection state changes */ - public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { - if (mScanController != null) { - mScanController.notifyProfileConnectionStateChange(profile, fromState, toState); - } - } - class ServerDeathRecipient implements IBinder.DeathRecipient { int mAppIf; private String mPackageName; @@ -833,133 +817,6 @@ public class GattService extends ProfileService { } @Override - public void startAdvertisingSet( - AdvertisingSetParameters parameters, - AdvertiseData advertiseData, - AdvertiseData scanResponse, - PeriodicAdvertisingParameters periodicParameters, - AdvertiseData periodicData, - int duration, - int maxExtAdvEvents, - int serverIf, - IAdvertisingSetCallback callback, - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.startAdvertisingSet( - parameters, - advertiseData, - scanResponse, - periodicParameters, - periodicData, - duration, - maxExtAdvEvents, - serverIf, - callback, - attributionSource); - } - - @Override - public void stopAdvertisingSet( - IAdvertisingSetCallback callback, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.stopAdvertisingSet(callback, attributionSource); - } - - @Override - public void getOwnAddress(int advertiserId, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.getOwnAddress(advertiserId, attributionSource); - } - - @Override - public void enableAdvertisingSet( - int advertiserId, - boolean enable, - int duration, - int maxExtAdvEvents, - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.enableAdvertisingSet( - advertiserId, enable, duration, maxExtAdvEvents, attributionSource); - } - - @Override - public void setAdvertisingData( - int advertiserId, AdvertiseData data, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.setAdvertisingData(advertiserId, data, attributionSource); - } - - @Override - public void setScanResponseData( - int advertiserId, AdvertiseData data, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.setScanResponseData(advertiserId, data, attributionSource); - } - - @Override - public void setAdvertisingParameters( - int advertiserId, - AdvertisingSetParameters parameters, - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.setAdvertisingParameters(advertiserId, parameters, attributionSource); - } - - @Override - public void setPeriodicAdvertisingParameters( - int advertiserId, - PeriodicAdvertisingParameters parameters, - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.setPeriodicAdvertisingParameters(advertiserId, parameters, attributionSource); - } - - @Override - public void setPeriodicAdvertisingData( - int advertiserId, AdvertiseData data, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.setPeriodicAdvertisingData(advertiserId, data, attributionSource); - } - - @Override - public void setPeriodicAdvertisingEnable( - int advertiserId, boolean enable, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return; - } - service.setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource); - } - - @Override public void disconnectAll(AttributionSource attributionSource) { GattService service = getService(); if (service == null) { @@ -967,119 +824,7 @@ public class GattService extends ProfileService { } service.disconnectAll(attributionSource); } - - @Override - public List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods( - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "GattService getSupportedDistanceMeasurementMethods") - || !Utils.checkConnectPermissionForDataDelivery( - service, - attributionSource, - "GattService getSupportedDistanceMeasurementMethods")) { - return Collections.emptyList(); - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return Arrays.asList(service.getSupportedDistanceMeasurementMethods()); - } - - @Override - public void startDistanceMeasurement( - ParcelUuid uuid, - DistanceMeasurementParams distanceMeasurementParams, - IDistanceMeasurementCallback callback, - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "startDistanceMeasurement") - || !Utils.checkConnectPermissionForDataDelivery( - service, attributionSource, "GattService startDistanceMeasurement")) { - return; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - service.startDistanceMeasurement(uuid.getUuid(), distanceMeasurementParams, callback); - } - - @Override - public int stopDistanceMeasurement( - ParcelUuid uuid, - BluetoothDevice device, - int method, - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } else if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "stopDistanceMeasurement")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } else if (!Utils.checkConnectPermissionForDataDelivery( - service, attributionSource, "GattService stopDistanceMeasurement")) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.stopDistanceMeasurement(uuid.getUuid(), device, method); - } - - @Override - public int getChannelSoundingMaxSupportedSecurityLevel( - BluetoothDevice remoteDevice, AttributionSource attributionSource) { - GattService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "GattService getChannelSoundingMaxSupportedSecurityLevel") - || !Utils.checkConnectPermissionForDataDelivery( - service, - attributionSource, - "GattService getChannelSoundingMaxSupportedSecurityLevel")) { - return ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getChannelSoundingMaxSupportedSecurityLevel(remoteDevice); - } - - @Override - public int getLocalChannelSoundingMaxSupportedSecurityLevel( - AttributionSource attributionSource) { - GattService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, - TAG, - "GattService getLocalChannelSoundingMaxSupportedSecurityLevel") - || !Utils.checkConnectPermissionForDataDelivery( - service, - attributionSource, - "GattService getLocalChannelSoundingMaxSupportedSecurityLevel")) { - return ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getLocalChannelSoundingMaxSupportedSecurityLevel(); - } - - @Override - public int[] getChannelSoundingSupportedSecurityLevels( - AttributionSource attributionSource) { - GattService service = getService(); - - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "GattService getChannelSoundingSupportedSecurityLevels") - || !Utils.checkConnectPermissionForDataDelivery( - service, - attributionSource, - "GattService getChannelSoundingSupportedSecurityLevels")) { - return new int[0]; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getChannelSoundingSupportedSecurityLevels().stream() - .mapToInt(i -> i) - .toArray(); - } } - ; /************************************************************************** * Callback functions - CLIENT @@ -1750,191 +1495,6 @@ public class GattService extends ProfileService { } /************************************************************************** - * ADVERTISING SET - *************************************************************************/ - @RequiresPermission( - allOf = { - BLUETOOTH_ADVERTISE, - BLUETOOTH_PRIVILEGED, - }, - conditional = true) - void startAdvertisingSet( - AdvertisingSetParameters parameters, - AdvertiseData advertiseData, - AdvertiseData scanResponse, - PeriodicAdvertisingParameters periodicParameters, - AdvertiseData periodicData, - int duration, - int maxExtAdvEvents, - int serverIf, - IAdvertisingSetCallback callback, - AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService startAdvertisingSet")) { - return; - } - if (parameters.getOwnAddressType() != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT - || serverIf != 0 - || parameters.isDirected()) { - this.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - } - mAdvertiseManager.startAdvertisingSet( - parameters, - advertiseData, - scanResponse, - periodicParameters, - periodicData, - duration, - maxExtAdvEvents, - serverIf, - callback, - attributionSource); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService stopAdvertisingSet")) { - return; - } - mAdvertiseManager.stopAdvertisingSet(callback); - } - - @RequiresPermission( - allOf = { - BLUETOOTH_ADVERTISE, - BLUETOOTH_PRIVILEGED, - }) - void getOwnAddress(int advertiserId, AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService getOwnAddress")) { - return; - } - this.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - mAdvertiseManager.getOwnAddress(advertiserId); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void enableAdvertisingSet( - int advertiserId, - boolean enable, - int duration, - int maxExtAdvEvents, - AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService enableAdvertisingSet")) { - return; - } - mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void setAdvertisingData( - int advertiserId, AdvertiseData data, AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService setAdvertisingData")) { - return; - } - mAdvertiseManager.setAdvertisingData(advertiserId, data); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void setScanResponseData( - int advertiserId, AdvertiseData data, AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService setScanResponseData")) { - return; - } - mAdvertiseManager.setScanResponseData(advertiserId, data); - } - - @RequiresPermission( - allOf = { - BLUETOOTH_ADVERTISE, - BLUETOOTH_PRIVILEGED, - }, - conditional = true) - void setAdvertisingParameters( - int advertiserId, - AdvertisingSetParameters parameters, - AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService setAdvertisingParameters")) { - return; - } - if (parameters.getOwnAddressType() != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT - || parameters.isDirected()) { - this.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - } - mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void setPeriodicAdvertisingParameters( - int advertiserId, - PeriodicAdvertisingParameters parameters, - AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService setPeriodicAdvertisingParameters")) { - return; - } - mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void setPeriodicAdvertisingData( - int advertiserId, AdvertiseData data, AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService setPeriodicAdvertisingData")) { - return; - } - mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data); - } - - @RequiresPermission(BLUETOOTH_ADVERTISE) - void setPeriodicAdvertisingEnable( - int advertiserId, boolean enable, AttributionSource attributionSource) { - if (!Utils.checkAdvertisePermissionForDataDelivery( - this, attributionSource, "GattService setPeriodicAdvertisingEnable")) { - return; - } - mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable); - } - - /************************************************************************** - * Distance Measurement - *************************************************************************/ - - DistanceMeasurementMethod[] getSupportedDistanceMeasurementMethods() { - return mDistanceMeasurementManager.getSupportedDistanceMeasurementMethods(); - } - - void startDistanceMeasurement( - UUID uuid, - DistanceMeasurementParams distanceMeasurementParams, - IDistanceMeasurementCallback callback) { - mDistanceMeasurementManager.startDistanceMeasurement( - uuid, distanceMeasurementParams, callback); - } - - int stopDistanceMeasurement(UUID uuid, BluetoothDevice device, int method) { - return mDistanceMeasurementManager.stopDistanceMeasurement(uuid, device, method, false); - } - - int getChannelSoundingMaxSupportedSecurityLevel(BluetoothDevice remoteDevice) { - return mDistanceMeasurementManager.getChannelSoundingMaxSupportedSecurityLevel( - remoteDevice); - } - - int getLocalChannelSoundingMaxSupportedSecurityLevel() { - return mDistanceMeasurementManager.getLocalChannelSoundingMaxSupportedSecurityLevel(); - } - - Set<Integer> getChannelSoundingSupportedSecurityLevels() { - return mDistanceMeasurementManager.getChannelSoundingSupportedSecurityLevels(); - } - - /************************************************************************** * GATT Service functions - CLIENT *************************************************************************/ @@ -3350,6 +2910,18 @@ public class GattService extends ProfileService { } /************************************************************************** + * Binder functions + *************************************************************************/ + + public IBinder getBluetoothAdvertise() { + return mAdvertiseManager.getBinder(); + } + + public IBinder getDistanceMeasurement() { + return mDistanceMeasurementManager.getBinder(); + } + + /************************************************************************** * Private functions *************************************************************************/ diff --git a/android/app/src/com/android/bluetooth/gatt/GattServiceConfig.java b/android/app/src/com/android/bluetooth/gatt/GattServiceConfig.kt index cbf574639c..c31521d6a4 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattServiceConfig.java +++ b/android/app/src/com/android/bluetooth/gatt/GattServiceConfig.kt @@ -14,10 +14,9 @@ * limitations under the License. */ -package com.android.bluetooth.gatt; +package com.android.bluetooth.gatt -/** GattService configuration. */ -public class GattServiceConfig { - public static final String TAG_PREFIX = "BtGatt."; - public static final boolean DEBUG_ADMIN = false; +object GattServiceConfig { + @JvmField val TAG_PREFIX = "BtGatt." + @JvmField val DEBUG_ADMIN = false } diff --git a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java index a48abbb9d3..0f654b8ccd 100644 --- a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java +++ b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java @@ -48,7 +48,6 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; -import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -180,18 +179,12 @@ public class HeadsetClientService extends ProfileService { int hfToAmVol(int hfVol) { int amRange = mMaxAmVcVol - mMinAmVcVol; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; - int amVol = 0; - if (Flags.headsetClientAmHfVolumeSymmetric()) { - amVol = - (int) - Math.round( - (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME) - * ((double) amRange / hfRange)) - + mMinAmVcVol; - } else { - int amOffset = (amRange * (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME)) / hfRange; - amVol = mMinAmVcVol + amOffset; - } + int amVol = + (int) + Math.round( + (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME) + * ((double) amRange / hfRange)) + + mMinAmVcVol; Log.d(TAG, "HF -> AM " + hfVol + " " + amVol); return amVol; } @@ -199,15 +192,9 @@ public class HeadsetClientService extends ProfileService { int amToHfVol(int amVol) { int amRange = (mMaxAmVcVol > mMinAmVcVol) ? (mMaxAmVcVol - mMinAmVcVol) : 1; int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME; - int hfVol = 0; - if (Flags.headsetClientAmHfVolumeSymmetric()) { - hfVol = - (int) Math.round((amVol - mMinAmVcVol) * ((double) hfRange / amRange)) - + MIN_HFP_SCO_VOICE_CALL_VOLUME; - } else { - int hfOffset = (hfRange * (amVol - mMinAmVcVol)) / amRange; - hfVol = MIN_HFP_SCO_VOICE_CALL_VOLUME + hfOffset; - } + int hfVol = + (int) Math.round((amVol - mMinAmVcVol) * ((double) hfRange / amRange)) + + MIN_HFP_SCO_VOICE_CALL_VOLUME; Log.d(TAG, "AM -> HF " + amVol + " " + hfVol); return hfVol; } diff --git a/android/app/src/com/android/bluetooth/hid/HidHostService.java b/android/app/src/com/android/bluetooth/hid/HidHostService.java index 70d69c8c80..2dda64f4b3 100644 --- a/android/app/src/com/android/bluetooth/hid/HidHostService.java +++ b/android/app/src/com/android/bluetooth/hid/HidHostService.java @@ -87,10 +87,6 @@ public class HidHostService extends ProfileService { } } - void setState(int state) { - setState(mSelectedTransport, state); - } - @Override public String toString() { return ("Selected transport=" + mSelectedTransport) @@ -198,20 +194,6 @@ public class HidHostService extends ProfileService { private byte[] getByteAddress(BluetoothDevice device, int transport) { final ParcelUuid[] uuids = mAdapterService.getRemoteUuids(device); - if (!Flags.allowSwitchingHidAndHogp()) { - boolean hogpSupported = Utils.arrayContains(uuids, BluetoothUuid.HOGP); - boolean headtrackerSupported = - Utils.arrayContains(uuids, HidHostService.ANDROID_HEADTRACKER_UUID); - - if (hogpSupported || headtrackerSupported) { - // Use pseudo address when HOGP is available - return Utils.getByteAddress(device); - } else { - // Otherwise use identity address - return getIdentityAddress(device); - } - } - if (transport == BluetoothDevice.TRANSPORT_LE) { // Use pseudo address when HOGP is to be used return Utils.getByteAddress(device); @@ -331,11 +313,6 @@ public class HidHostService extends ProfileService { "nativeConnect: Connection attempt failed." + (" device=" + device) + (" transport=" + transport)); - - if (!Flags.allowSwitchingHidAndHogp()) { - updateConnectionState(device, transport, BluetoothProfile.STATE_DISCONNECTING); - updateConnectionState(device, transport, BluetoothProfile.STATE_DISCONNECTED); - } return false; } return true; @@ -362,10 +339,6 @@ public class HidHostService extends ProfileService { "nativeDisconnect: Disconnection attempt failed." + (" device=" + device) + (" transport=" + transport)); - if (!Flags.allowSwitchingHidAndHogp()) { - updateConnectionState(device, transport, BluetoothProfile.STATE_DISCONNECTING); - updateConnectionState(device, transport, BluetoothProfile.STATE_DISCONNECTED); - } return false; } return true; @@ -434,9 +407,6 @@ public class HidHostService extends ProfileService { }; private void handleMessageSendData(Message msg) { - if (!Flags.allowSwitchingHidAndHogp()) { - return; - } BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj); Bundle data = msg.getData(); @@ -630,43 +600,37 @@ public class HidHostService extends ProfileService { int state = msg.arg2; int prevState = getState(device, transport); - if (Flags.allowSwitchingHidAndHogp()) { - InputDevice inputDevice = mInputDevices.get(device); - if (inputDevice != null) { - // Update transport if it was not resolved already - if (inputDevice.mSelectedTransport == BluetoothDevice.TRANSPORT_AUTO) { - inputDevice.mSelectedTransport = transport; - setTransport(device, transport); - } - } else { - // ACCEPTING state for unknown device indicates that this device - // was loaded from storage. Add it in the record. - if (state == STATE_ACCEPTING) { - setTransport(device, transport); - } else { - Log.e( - TAG, - "handleMessageConnectStateChanged: Disconnect and unknown inputDevice" - + (" device=" + device) - + (" state=" + state)); - nativeDisconnect(device, transport, false); - return; - } + InputDevice inputDevice = mInputDevices.get(device); + if (inputDevice != null) { + // Update transport if it was not resolved already + if (inputDevice.mSelectedTransport == BluetoothDevice.TRANSPORT_AUTO) { + inputDevice.mSelectedTransport = transport; + setTransport(device, transport); } - - if (transport != getTransport(device)) { - Log.w( + } else { + // ACCEPTING state for unknown device indicates that this device + // was loaded from storage. Add it in the record. + if (state == STATE_ACCEPTING) { + setTransport(device, transport); + } else { + Log.e( TAG, - "handleMessageConnectStateChanged: Not preferred transport in message" + "handleMessageConnectStateChanged: Disconnect and unknown inputDevice" + (" device=" + device) - + (" transport=" + transport) - + (" newState=" + state) - + (" prevState=" + prevState)); + + (" state=" + state)); + nativeDisconnect(device, transport, false); + return; } - } else { - // Only TRANSPORT_AUTO should be used when allowSwitchingHidAndHogp is disabled - transport = BluetoothDevice.TRANSPORT_AUTO; - setTransport(device, BluetoothDevice.TRANSPORT_AUTO); + } + + if (transport != getTransport(device)) { + Log.w( + TAG, + "handleMessageConnectStateChanged: Not preferred transport in message" + + (" device=" + device) + + (" transport=" + transport) + + (" newState=" + state) + + (" prevState=" + prevState)); } Log.d( @@ -676,11 +640,10 @@ public class HidHostService extends ProfileService { + (" newState=" + state) + (" prevState=" + prevState)); - boolean connectionAllowed = true; // Process connection if (prevState == BluetoothProfile.STATE_DISCONNECTED && state == BluetoothProfile.STATE_CONNECTED) { - connectionAllowed = processConnection(device, transport); + processConnection(device, transport); } // ACCEPTING state has to be treated as DISCONNECTED state @@ -688,10 +651,7 @@ public class HidHostService extends ProfileService { if (state == STATE_ACCEPTING) { reportedState = BluetoothProfile.STATE_DISCONNECTED; } - - if (Flags.allowSwitchingHidAndHogp() || connectionAllowed) { - updateConnectionState(device, transport, reportedState); - } + updateConnectionState(device, transport, reportedState); } private void handleMessageDisconnect(Message msg) { @@ -699,12 +659,9 @@ public class HidHostService extends ProfileService { int connectionPolicy = msg.arg1; boolean reconnectAllowed = true; - if (Flags.allowSwitchingHidAndHogp()) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - reconnectAllowed = false; - } + if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + reconnectAllowed = false; } - nativeDisconnect(device, getTransport(device), reconnectAllowed); } @@ -712,19 +669,16 @@ public class HidHostService extends ProfileService { BluetoothDevice device = (BluetoothDevice) msg.obj; InputDevice inputDevice = getOrCreateInputDevice(device); - if (Flags.allowSwitchingHidAndHogp()) { - int connectionPolicy = getConnectionPolicy(device); - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - Log.e( - TAG, - "handleMessageConnect: Connection not allowed." - + (" device=" + device) - + (" connectionPolicy=" + connectionPolicy)); + int connectionPolicy = getConnectionPolicy(device); + if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { + Log.e( + TAG, + "handleMessageConnect: Connection not allowed." + + (" device=" + device) + + (" connectionPolicy=" + connectionPolicy)); - return; - } + return; } - nativeConnect(device, inputDevice.mSelectedTransport); } @@ -737,7 +691,7 @@ public class HidHostService extends ProfileService { * @return true if transport matches, otherwise false */ private boolean checkTransport(BluetoothDevice device, int transport, int message) { - if (Flags.allowSwitchingHidAndHogp() && getTransport(device) != transport) { + if (getTransport(device) != transport) { Log.w( TAG, "checkTransport:" @@ -763,12 +717,7 @@ public class HidHostService extends ProfileService { + (" device=" + device) + (" connectionPolicy=" + getConnectionPolicy(device))); - if (Flags.allowSwitchingHidAndHogp()) { - nativeDisconnect(device, transport, false); - } else { - mNativeInterface.virtualUnPlug( - getByteAddress(device), getAddressType(device), getTransport(device)); - } + nativeDisconnect(device, transport, false); return false; } return true; @@ -1217,11 +1166,6 @@ public class HidHostService extends ProfileService { return false; } - if (!Flags.allowSwitchingHidAndHogp()) { - return mNativeInterface.sendData( - getByteAddress(device), getAddressType(device), getTransport(device), report); - } - Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA, device); Bundle data = new Bundle(); data.putString(BluetoothHidHost.EXTRA_REPORT, report); @@ -1321,39 +1265,29 @@ public class HidHostService extends ProfileService { */ private void updateConnectionState(BluetoothDevice device, int transport, int newState) { InputDevice inputDevice = mInputDevices.get(device); - int prevState = BluetoothProfile.STATE_DISCONNECTED; - if (Flags.allowSwitchingHidAndHogp()) { - if (inputDevice == null) { - Log.w( - TAG, - "updateConnectionState: requested on unknown inputDevice" - + (" device=" + device) - + (" newState=" + newState) - + (" transport=" + transport)); - return; - } - - if (transport == BluetoothDevice.TRANSPORT_AUTO) { - Log.w( - TAG, - "updateConnectionState: requested with AUTO transport" - + (" device=" + device) - + (" newState=" + newState)); - return; - } + if (inputDevice == null) { + Log.w( + TAG, + "updateConnectionState: requested on unknown inputDevice" + + (" device=" + device) + + (" newState=" + newState) + + (" transport=" + transport)); + return; + } - prevState = inputDevice.getState(transport); - inputDevice.setState(transport, newState); - } else { - if (inputDevice == null) { - inputDevice = getOrCreateInputDevice(device); - } - prevState = inputDevice.getState(); - setTransport(device, transport); - inputDevice.setState(newState); + if (transport == BluetoothDevice.TRANSPORT_AUTO) { + Log.w( + TAG, + "updateConnectionState: requested with AUTO transport" + + (" device=" + device) + + (" newState=" + newState)); + return; } + int prevState = inputDevice.getState(transport); + inputDevice.setState(transport, newState); + if (prevState == newState) { Log.d( TAG, @@ -1393,9 +1327,7 @@ public class HidHostService extends ProfileService { intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - if (Flags.allowSwitchingHidAndHogp()) { - intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, transport); - } + intent.putExtra(BluetoothDevice.EXTRA_TRANSPORT, transport); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); sendBroadcastAsUser( intent, diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java index decf90c3a5..8c9ca8735b 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -2027,38 +2027,52 @@ public class LeAudioService extends ProfileService { private class AudioServerScanCallback extends IScannerCallback.Stub { // See BluetoothLeScanner.BleScanCallbackWrapper.mScannerId - int mScannerId = 0; + static final int SCANNER_NOT_INITIALIZED = -2; + static final int SCANNER_INITIALIZING = -1; + int mScannerId = SCANNER_NOT_INITIALIZED; synchronized void startBackgroundScan() { - if (mScannerId != 0) { - Log.d(TAG, "Scanner is already registered with id " + mScannerId); + if (mScannerId >= 0) { + Log.i( + TAG, + "startBackgroundScan: Scanner is already registered with id " + mScannerId); return; } + + if (mScannerId == SCANNER_INITIALIZING) { + Log.i(TAG, "startBackgroundScan: Scanner is already initializing"); + return; + } + + mScannerId = SCANNER_INITIALIZING; + mAdapterService .getBluetoothScanController() - .getTransitionalScanHelper() .registerScannerInternal(this, getAttributionSource(), null); } synchronized void stopBackgroundScan() { - if (mScannerId == 0) { - Log.d(TAG, "Scanner is already unregistered"); + if (mScannerId < 0) { + Log.d(TAG, "Scanner is not running (mScannerId=" + mScannerId + ")"); return; } mAdapterService .getBluetoothScanController() - .getTransitionalScanHelper() .stopScanInternal(mScannerId); mAdapterService .getBluetoothScanController() - .getTransitionalScanHelper() .unregisterScannerInternal(mScannerId); - mScannerId = 0; + mScannerId = SCANNER_NOT_INITIALIZED; } @Override public synchronized void onScannerRegistered(int status, int scannerId) { + Log.d(TAG, "onScannerRegistered: status: " + status + ", id:" + scannerId); + if (status != 0) { + mScannerId = SCANNER_NOT_INITIALIZED; + return; + } mScannerId = scannerId; /* Filter we are building here will not match to anything. @@ -2079,7 +2093,6 @@ public class LeAudioService extends ProfileService { mAdapterService .getBluetoothScanController() - .getTransitionalScanHelper() .startScanInternal(scannerId, settings, List.of(filter)); } @@ -2939,7 +2952,7 @@ public class LeAudioService extends ProfileService { return false; } - return bassClientService.isAnyReceiverReceivingBroadcast(getGroupDevices(groupId)); + return bassClientService.isAnyReceiverActive(getGroupDevices(groupId)); } private void notifyGroupStreamStatusChanged(int groupId, int groupStreamStatus) { @@ -3656,7 +3669,8 @@ public class LeAudioService extends ProfileService { } if (leaudioBigDependsOnAudioState()) { - if (mAwaitingBroadcastCreateResponse) { + if (mAwaitingBroadcastCreateResponse + && !Flags.leaudioBroadcastPrimaryGroupSelection()) { updateFallbackUnicastGroupIdForBroadcast(groupId); } } else { @@ -4025,11 +4039,6 @@ public class LeAudioService extends ProfileService { return; } - if (descriptor.mGroupId != LE_AUDIO_GROUP_ID_INVALID) { - /* In case device is still in the group, let's remove it */ - mNativeInterface.groupRemoveNode(descriptor.mGroupId, device); - } - descriptor.mGroupId = LE_AUDIO_GROUP_ID_INVALID; descriptor.mSinkAudioLocation = BluetoothLeAudio.AUDIO_LOCATION_INVALID; descriptor.mDirection = AUDIO_DIRECTION_NONE; @@ -4193,6 +4202,11 @@ public class LeAudioService extends ProfileService { false, hasFallbackDevice, false); + /* Set by default earliest connected device */ + if (Flags.leaudioBroadcastPrimaryGroupSelection() + && mUnicastGroupIdDeactivatedForBroadcastTransition == groupId) { + setDefaultBroadcastToUnicastFallbackGroup(); + } return; } diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java index ee743f3265..8d1fec5c72 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioStateMachine.java @@ -50,6 +50,7 @@ import android.os.Message; import android.util.Log; import com.android.bluetooth.btservice.ProfileService; +import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -276,7 +277,12 @@ final class LeAudioStateMachine extends StateMachine { switch (message.what) { case CONNECT: - deferMessage(message); + if (Flags.leaudioSmIgnoreConnectEventsInConnectingState() + && !hasDeferredMessages(DISCONNECT)) { + Log.w(TAG, "Connecting: CONNECT ignored: " + mDevice); + } else { + deferMessage(message); + } break; case CONNECT_TIMEOUT: Log.w(TAG, "Connecting connection timeout: " + mDevice); diff --git a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java index 0780d54189..dc7284b94b 100644 --- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java +++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java @@ -65,8 +65,8 @@ public class AppScanStats { // ScannerMap here is needed to grab Apps ScannerMap mScannerMap; - // TransitionalScanHelper is needed to add scan event protos to be dumped later - final TransitionalScanHelper mScanHelper; + // ScanController is needed to add scan event protos to be dumped later + final ScanController mScanController; // Battery stats is used to keep track of scans and result stats BatteryStatsManager mBatteryStatsManager; @@ -173,13 +173,13 @@ public class AppScanStats { WorkSource source, ScannerMap map, AdapterService adapterService, - TransitionalScanHelper scanHelper, + ScanController scanController, TimeProvider timeProvider) { mAdapterService = requireNonNull(adapterService); mTimeProvider = requireNonNull(timeProvider); mAppName = name; mScannerMap = map; - mScanHelper = scanHelper; + mScanController = scanController; mBatteryStatsManager = adapterService.getSystemService(BatteryStatsManager.class); if (source == null) { @@ -310,7 +310,7 @@ public class AppScanStats { .setEventTimeMillis(System.currentTimeMillis()) .setInitiator(truncateAppName(mAppName)) .build(); - mScanHelper.addScanEvent(scanEvent); + mScanController.addScanEvent(scanEvent); if (!isScanning()) { mScanStartTime = startTime; @@ -362,7 +362,7 @@ public class AppScanStats { .setInitiator(truncateAppName(mAppName)) .setNumberResults(scan.results) .build(); - mScanHelper.addScanEvent(scanEvent); + mScanController.addScanEvent(scanEvent); mTotalScanTime += scanDuration; long activeDuration = scanDuration - scan.suspendDuration; diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanController.java b/android/app/src/com/android/bluetooth/le_scan/ScanController.java index e992a8da16..a8f5a4025e 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanController.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanController.java @@ -16,48 +16,90 @@ package com.android.bluetooth.le_scan; +import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.Manifest.permission.BLUETOOTH_SCAN; +import static android.Manifest.permission.UPDATE_DEVICE_STATS; + +import static com.android.bluetooth.Utils.checkCallerTargetSdk; + import static java.util.Objects.requireNonNull; +import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; +import android.app.AppOpsManager; import android.app.PendingIntent; +import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothUtils; import android.bluetooth.IBluetoothScan; +import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.IPeriodicAdvertisingCallback; import android.bluetooth.le.IScannerCallback; +import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; +import android.companion.AssociationInfo; +import android.companion.CompanionDeviceManager; import android.content.AttributionSource; +import android.content.Intent; +import android.net.MacAddress; +import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.UserHandle; import android.os.WorkSource; +import android.provider.DeviceConfig; import android.text.format.DateUtils; import android.util.Log; import com.android.bluetooth.BluetoothMetricsProto; +import com.android.bluetooth.R; +import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.btservice.BluetoothAdapterProxy; import com.android.bluetooth.btservice.ProfileService; +import com.android.bluetooth.util.NumberUtils; +import com.android.internal.annotations.VisibleForTesting; import libcore.util.HexEncoding; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; +import java.util.stream.Collectors; public class ScanController { private static final String TAG = ScanController.class.getSimpleName(); - public final TransitionalScanHelper mTransitionalScanHelper; - public final HandlerThread mScanThread; + // Batch scan related constants. + private static final int TRUNCATED_RESULT_SIZE = 11; - private final BluetoothScanBinder mBinder; + /** The default floor value for LE batch scan report delays greater than 0 */ + @VisibleForTesting static final long DEFAULT_REPORT_DELAY_FLOOR = 5000; - private boolean mIsAvailable; + private static final int NUM_SCAN_EVENTS_KEPT = 20; - private volatile boolean mTestModeEnabled = false; - private final Looper mMainLooper; - private Handler mTestModeHandler; - private final Object mTestModeLock = new Object(); + // onFoundLost related constants + @VisibleForTesting static final int ADVT_STATE_ONFOUND = 0; + private static final int ADVT_STATE_ONLOST = 1; + + private static final int ET_LEGACY_MASK = 0x10; /** Example raw beacons captured from a Blue Charm BC011 */ private static final String[] TEST_MODE_BEACONS = @@ -69,15 +111,103 @@ public class ScanController { "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000", }; + static class PendingIntentInfo { + public PendingIntent intent; + public ScanSettings settings; + public List<ScanFilter> filters; + public String callingPackage; + public int callingUid; + + @Override + public boolean equals(Object other) { + if (!(other instanceof PendingIntentInfo)) { + return false; + } + return intent.equals(((PendingIntentInfo) other).intent); + } + + @Override + public int hashCode() { + return intent == null ? 0 : intent.hashCode(); + } + } + + private final PendingIntent.CancelListener mScanIntentCancelListener = + new PendingIntent.CancelListener() { + public void onCanceled(PendingIntent intent) { + Log.d(TAG, "scanning PendingIntent canceled"); + stopScanInternal(intent); + } + }; + + private final AdapterService mAdapterService; + + private final HashMap<Integer, Integer> mFilterIndexToMsftAdvMonitorMap = new HashMap<>(); + private final String mExposureNotificationPackage; + + private final AppOpsManager mAppOps; + private final CompanionDeviceManager mCompanionManager; + private final PeriodicScanManager mPeriodicScanManager; + private final ScanManager mScanManager; + + public final HandlerThread mScanThread; + + private final BluetoothScanBinder mBinder; + + /** Internal list of scan events to use with the proto */ + private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents = + new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); + + private final Predicate<ScanResult> mLocationDenylistPredicate; + + private ScannerMap mScannerMap = new ScannerMap(); + + private boolean mIsAvailable; + + private volatile boolean mTestModeEnabled = false; + private final Looper mMainLooper; + private Handler mTestModeHandler; + private final Object mTestModeLock = new Object(); + public ScanController(AdapterService adapterService) { - mTransitionalScanHelper = - new TransitionalScanHelper(requireNonNull(adapterService), () -> mTestModeEnabled); + mAdapterService = requireNonNull(adapterService); + mExposureNotificationPackage = + mAdapterService.getString(R.string.exposure_notification_package); + mLocationDenylistPredicate = + (scanResult) -> { + final MacAddress parsedAddress = + MacAddress.fromString(scanResult.getDevice().getAddress()); + if (mAdapterService + .getLocationDenylistMac() + .test(parsedAddress.toByteArray())) { + Log.v(TAG, "Skipping device matching denylist: " + scanResult.getDevice()); + return true; + } + final ScanRecord scanRecord = scanResult.getScanRecord(); + if (scanRecord.matchesAnyField( + mAdapterService.getLocationDenylistAdvertisingData())) { + Log.v(TAG, "Skipping data matching denylist: " + scanRecord); + return true; + } + return false; + }; mMainLooper = adapterService.getMainLooper(); mBinder = new BluetoothScanBinder(this); mIsAvailable = true; mScanThread = new HandlerThread("BluetoothScanManager"); mScanThread.start(); - mTransitionalScanHelper.start(mScanThread.getLooper()); + mAppOps = mAdapterService.getSystemService(AppOpsManager.class); + mCompanionManager = mAdapterService.getSystemService(CompanionDeviceManager.class); + mScanManager = + ScanObjectsFactory.getInstance() + .createScanManager( + mAdapterService, + this, + BluetoothAdapterProxy.getInstance(), + mScanThread.getLooper()); + + mPeriodicScanManager = + ScanObjectsFactory.getInstance().createPeriodicScanManager(mAdapterService); } public void stop() { @@ -85,17 +215,23 @@ public class ScanController { mIsAvailable = false; mBinder.clearScanController(); mScanThread.quitSafely(); - mTransitionalScanHelper.stop(); - mTransitionalScanHelper.cleanup(); + mScannerMap.clear(); + mScanManager.cleanup(); + mPeriodicScanManager.cleanup(); } - /** Notify Scan manager of bluetooth profile connection state changes */ - public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { - mTransitionalScanHelper.notifyProfileConnectionStateChange(profile, fromState, toState); + ScannerMap getScannerMap() { + return mScannerMap; } - public TransitionalScanHelper getTransitionalScanHelper() { - return mTransitionalScanHelper; + @VisibleForTesting + void setScannerMap(ScannerMap scannerMap) { + mScannerMap = scannerMap; + } + + /** Notify Scan manager of bluetooth profile connection state changes */ + public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { + mScanManager.handleBluetoothProfileConnectionStateChanged(profile, fromState, toState); } public IBinder getBinder() { @@ -113,7 +249,7 @@ public class ScanController { return; } for (String test : TEST_MODE_BEACONS) { - mTransitionalScanHelper.onScanResultInternal( + onScanResultInternal( 0x1b, 0x1, "DD:34:02:05:5C:4D", @@ -141,18 +277,1453 @@ public class ScanController { } } + /************************************************************************** + * Callback functions - CLIENT + *************************************************************************/ + + // EN format defined here: + // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf + private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = + new byte[] { + // size 2, flag field, flags byte (value is not important) + (byte) 0x02, (byte) 0x01 + }; + + private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1; + private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = + new byte[] { + // size 3, complete 16 bit UUID, EN UUID + (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD, + // size 23, data for 16 bit UUID, EN UUID + (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD, + // ...payload + }; + private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2; + + private static boolean arrayStartsWith(byte[] array, byte[] prefix) { + if (array.length < prefix.length) { + return false; + } + for (int i = 0; i < prefix.length; i++) { + if (prefix[i] != array[i]) { + return false; + } + } + return true; + } + + private ScanResult getSanitizedExposureNotification(ScanResult result) { + ScanRecord record = result.getScanRecord(); + // Remove the flags part of the payload, if present + if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH + && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) { + record = + ScanRecord.parseFromBytes( + Arrays.copyOfRange( + record.getBytes(), + EXPOSURE_NOTIFICATION_FLAGS_LENGTH, + record.getBytes().length)); + } + + if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) { + return null; + } + if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) { + return null; + } + + return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0); + } + + /** Callback method for a scan result. */ + void onScanResult( + int eventType, + int addressType, + String address, + int primaryPhy, + int secondaryPhy, + int advertisingSid, + int txPower, + int rssi, + int periodicAdvInt, + byte[] advData, + String originalAddress) { + // When in testing mode, ignore all real-world events + if (mTestModeEnabled) return; + + AppScanStats.recordScanRadioResultCount(); + onScanResultInternal( + eventType, + addressType, + address, + primaryPhy, + secondaryPhy, + advertisingSid, + txPower, + rssi, + periodicAdvInt, + advData, + originalAddress); + } + + private void onScanResultInternal( + int eventType, + int addressType, + String address, + int primaryPhy, + int secondaryPhy, + int advertisingSid, + int txPower, + int rssi, + int periodicAdvInt, + byte[] advData, + String originalAddress) { + Log.v( + TAG, + "onScanResult() - eventType=0x" + + Integer.toHexString(eventType) + + ", addressType=" + + addressType + + ", address=" + + BluetoothUtils.toAnonymizedAddress(address) + + ", primaryPhy=" + + primaryPhy + + ", secondaryPhy=" + + secondaryPhy + + ", advertisingSid=0x" + + Integer.toHexString(advertisingSid) + + ", txPower=" + + txPower + + ", rssi=" + + rssi + + ", periodicAdvInt=0x" + + Integer.toHexString(periodicAdvInt) + + ", originalAddress=" + + originalAddress); + + String identityAddress = mAdapterService.getIdentityAddress(address); + if (!address.equals(identityAddress)) { + Log.v( + TAG, + "found identityAddress of " + + address + + ", replace originalAddress as " + + identityAddress); + originalAddress = identityAddress; + } + + byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62); + + for (ScanClient client : mScanManager.getRegularScanQueue()) { + ScannerMap.ScannerApp app = mScannerMap.getById(client.scannerId); + if (app == null) { + Log.v(TAG, "App is null; skip."); + continue; + } + + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(address, addressType); + + ScanSettings settings = client.settings; + byte[] scanRecordData; + // This is for compatibility with applications that assume fixed size scan data. + if (settings.getLegacy()) { + if ((eventType & ET_LEGACY_MASK) == 0) { + // If this is legacy scan, but nonlegacy result - skip. + Log.v(TAG, "Legacy scan, non legacy result; skip."); + continue; + } else { + // Some apps are used to fixed-size advertise data. + scanRecordData = legacyAdvData; + } + } else { + scanRecordData = advData; + } + + ScanRecord scanRecord = ScanRecord.parseFromBytes(scanRecordData); + ScanResult result = + new ScanResult( + device, + eventType, + primaryPhy, + secondaryPhy, + advertisingSid, + txPower, + rssi, + periodicAdvInt, + scanRecord, + SystemClock.elapsedRealtimeNanos()); + + if (client.hasDisavowedLocation) { + if (mLocationDenylistPredicate.test(result)) { + Log.i(TAG, "Skipping client for location deny list"); + continue; + } + } + + boolean hasPermission = hasScanResultPermission(client); + if (!hasPermission) { + for (String associatedDevice : client.associatedDevices) { + if (associatedDevice.equalsIgnoreCase(address)) { + hasPermission = true; + break; + } + } + } + if (!hasPermission && client.eligibleForSanitizedExposureNotification) { + ScanResult sanitized = getSanitizedExposureNotification(result); + if (sanitized != null) { + hasPermission = true; + result = sanitized; + } + } + boolean matchResult = matchesFilters(client, result, originalAddress); + if (!hasPermission || !matchResult) { + Log.v( + TAG, + "Skipping client: permission=" + hasPermission + " matches=" + matchResult); + continue; + } + + int callbackType = settings.getCallbackType(); + if (!(callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES + || callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH)) { + Log.v(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); + continue; + } + + try { + app.mAppScanStats.addResult(client.scannerId); + if (app.mCallback != null) { + app.mCallback.onScanResult(result); + } else { + Log.v(TAG, "Callback is null, sending scan results by pendingIntent"); + // Send the PendingIntent + ArrayList<ScanResult> results = new ArrayList<>(); + results.add(result); + sendResultsByPendingIntent( + app.mInfo, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); + } + } catch (RemoteException | PendingIntent.CanceledException e) { + Log.e(TAG, "Exception: " + e); + handleDeadScanClient(client); + } + } + } + + private void sendResultByPendingIntent( + PendingIntentInfo pii, ScanResult result, int callbackType, ScanClient client) { + ArrayList<ScanResult> results = new ArrayList<>(); + results.add(result); + try { + sendResultsByPendingIntent(pii, results, callbackType); + } catch (PendingIntent.CanceledException e) { + final long token = Binder.clearCallingIdentity(); + try { + stopScanInternal(client.scannerId); + unregisterScannerInternal(client.scannerId); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + + @SuppressWarnings("NonApiType") + private void sendResultsByPendingIntent( + PendingIntentInfo pii, ArrayList<ScanResult> results, int callbackType) + throws PendingIntent.CanceledException { + Intent extrasIntent = new Intent(); + extrasIntent.putParcelableArrayListExtra( + BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, results); + extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); + pii.intent.send(mAdapterService, 0, extrasIntent); + } + + private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) + throws PendingIntent.CanceledException { + Intent extrasIntent = new Intent(); + extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); + pii.intent.send(mAdapterService, 0, extrasIntent); + } + + /** Callback method for scanner registration. */ + void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) + throws RemoteException { + UUID uuid = new UUID(uuidMsb, uuidLsb); + Log.d( + TAG, + "onScannerRegistered() - UUID=" + + uuid + + ", scannerId=" + + scannerId + + ", status=" + + status); + + // First check the callback map + ScannerMap.ScannerApp cbApp = mScannerMap.getByUuid(uuid); + if (cbApp != null) { + if (status == 0) { + cbApp.mId = scannerId; + // If app is callback based, setup a death recipient. App will initiate the start. + // Otherwise, if PendingIntent based, start the scan directly. + if (cbApp.mCallback != null) { + cbApp.linkToDeath(new ScannerDeathRecipient(scannerId, cbApp.mName)); + } else { + continuePiStartScan(scannerId, cbApp); + } + } else { + mScannerMap.remove(scannerId); + } + if (cbApp.mCallback != null) { + cbApp.mCallback.onScannerRegistered(status, scannerId); + } + } + } + + /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ + private boolean hasScanResultPermission(final ScanClient client) { + if (client.hasNetworkSettingsPermission + || client.hasNetworkSetupWizardPermission + || client.hasScanWithoutLocationPermission) { + return true; + } + if (client.hasDisavowedLocation) { + return true; + } + return client.hasLocationPermission + && !Utils.blockedByLocationOff(mAdapterService, client.userHandle); + } + + // Check if a scan record matches a specific filters. + private boolean matchesFilters(ScanClient client, ScanResult scanResult) { + return matchesFilters(client, scanResult, null); + } + + // Check if a scan record matches a specific filters or original address + private boolean matchesFilters( + ScanClient client, ScanResult scanResult, String originalAddress) { + if (client.filters == null || client.filters.isEmpty()) { + // TODO: Do we really wanna return true here? + return true; + } + for (ScanFilter filter : client.filters) { + // Need to check the filter matches, and the original address without changing the API + if (filter.matches(scanResult)) { + return true; + } + if (originalAddress != null + && originalAddress.equalsIgnoreCase(filter.getDeviceAddress())) { + return true; + } + } + return false; + } + + private void handleDeadScanClient(ScanClient client) { + if (client.appDied) { + Log.w(TAG, "Already dead client " + client.scannerId); + return; + } + client.appDied = true; + if (client.stats != null) { + client.stats.isAppDead = true; + } + stopScanInternal(client.scannerId); + } + + /** Callback method for scan filter enablement/disablement. */ + void onScanFilterEnableDisabled(int action, int status, int clientIf) { + Log.d( + TAG, + "onScanFilterEnableDisabled() - clientIf=" + + clientIf + + ", status=" + + status + + ", action=" + + action); + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for configuration of scan filter params. */ + void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { + Log.d( + TAG, + "onScanFilterParamsConfigured() - clientIf=" + + clientIf + + ", status=" + + status + + ", action=" + + action + + ", availableSpace=" + + availableSpace); + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for configuration of scan filter. */ + void onScanFilterConfig( + int action, int status, int clientIf, int filterType, int availableSpace) { + Log.d( + TAG, + "onScanFilterConfig() - clientIf=" + + clientIf + + ", action = " + + action + + " status = " + + status + + ", filterType=" + + filterType + + ", availableSpace=" + + availableSpace); + + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for configuration of batch scan storage. */ + void onBatchScanStorageConfigured(int status, int clientIf) { + Log.d(TAG, "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for start/stop of batch scan. */ + // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. + void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { + Log.d( + TAG, + "onBatchScanStartStopped() - clientIf=" + + clientIf + + ", status=" + + status + + ", startStopAction=" + + startStopAction); + mScanManager.callbackDone(clientIf, status); + } + + ScanClient findBatchScanClientById(int scannerId) { + for (ScanClient client : mScanManager.getBatchScanQueue()) { + if (client.scannerId == scannerId) { + return client; + } + } + return null; + } + + /** Callback method for batch scan reports */ + void onBatchScanReports( + int status, int scannerId, int reportType, int numRecords, byte[] recordData) + throws RemoteException { + // When in testing mode, ignore all real-world events + if (mTestModeEnabled) return; + + AppScanStats.recordBatchScanRadioResultCount(numRecords); + onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); + } + + @VisibleForTesting + void onBatchScanReportsInternal( + int status, int scannerId, int reportType, int numRecords, byte[] recordData) + throws RemoteException { + Log.d( + TAG, + "onBatchScanReports() - scannerId=" + + scannerId + + ", status=" + + status + + ", reportType=" + + reportType + + ", numRecords=" + + numRecords); + + Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); + if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { + // We only support single client for truncated mode. + ScannerMap.ScannerApp app = mScannerMap.getById(scannerId); + if (app == null) { + return; + } + + ScanClient client = findBatchScanClientById(scannerId); + if (client == null) { + return; + } + + ArrayList<ScanResult> permittedResults; + if (hasScanResultPermission(client)) { + permittedResults = new ArrayList<ScanResult>(results); + } else { + permittedResults = new ArrayList<ScanResult>(); + for (ScanResult scanResult : results) { + for (String associatedDevice : client.associatedDevices) { + if (associatedDevice.equalsIgnoreCase( + scanResult.getDevice().getAddress())) { + permittedResults.add(scanResult); + } + } + } + if (permittedResults.isEmpty()) { + return; + } + } + + if (client.hasDisavowedLocation) { + permittedResults.removeIf(mLocationDenylistPredicate); + } + + if (app.mCallback != null) { + app.mCallback.onBatchScanResults(permittedResults); + } else { + // PendingIntent based + try { + sendResultsByPendingIntent( + app.mInfo, permittedResults, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); + } catch (PendingIntent.CanceledException e) { + Log.d(TAG, "Exception while sending result", e); + } + } + } else { + for (ScanClient client : mScanManager.getFullBatchScanQueue()) { + // Deliver results for each client. + deliverBatchScan(client, results); + } + } + mScanManager.callbackDone(scannerId, status); + } + + @SuppressWarnings("NonApiType") + private void sendBatchScanResults( + ScannerMap.ScannerApp app, ScanClient client, ArrayList<ScanResult> results) { + try { + if (app.mCallback != null) { + if (mScanManager.isAutoBatchScanClientEnabled(client)) { + Log.d(TAG, "sendBatchScanResults() to onScanResult()" + client); + for (ScanResult result : results) { + app.mAppScanStats.addResult(client.scannerId); + app.mCallback.onScanResult(result); + } + } else { + Log.d(TAG, "sendBatchScanResults() to onBatchScanResults()" + client); + app.mCallback.onBatchScanResults(results); + } + } else { + sendResultsByPendingIntent( + app.mInfo, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); + } + } catch (RemoteException | PendingIntent.CanceledException e) { + Log.e(TAG, "Exception: " + e); + handleDeadScanClient(client); + } + } + + // Check and deliver scan results for different scan clients. + private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) + throws RemoteException { + ScannerMap.ScannerApp app = mScannerMap.getById(client.scannerId); + if (app == null) { + return; + } + + ArrayList<ScanResult> permittedResults; + if (hasScanResultPermission(client)) { + permittedResults = new ArrayList<ScanResult>(allResults); + } else { + permittedResults = new ArrayList<ScanResult>(); + for (ScanResult scanResult : allResults) { + for (String associatedDevice : client.associatedDevices) { + if (associatedDevice.equalsIgnoreCase(scanResult.getDevice().getAddress())) { + permittedResults.add(scanResult); + } + } + } + if (permittedResults.isEmpty()) { + return; + } + } + + if (client.filters == null || client.filters.isEmpty()) { + sendBatchScanResults(app, client, permittedResults); + // TODO: Question to reviewer: Shouldn't there be a return here? + } + // Reconstruct the scan results. + ArrayList<ScanResult> results = new ArrayList<ScanResult>(); + for (ScanResult scanResult : permittedResults) { + if (matchesFilters(client, scanResult)) { + results.add(scanResult); + } + } + sendBatchScanResults(app, client, results); + } + + private Set<ScanResult> parseBatchScanResults( + int numRecords, int reportType, byte[] batchRecord) { + if (numRecords == 0) { + return Collections.emptySet(); + } + Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); + if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { + return parseTruncatedResults(numRecords, batchRecord); + } else { + return parseFullResults(numRecords, batchRecord); + } + } + + private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { + Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); + Set<ScanResult> results = new HashSet<ScanResult>(numRecords); + long now = SystemClock.elapsedRealtimeNanos(); + for (int i = 0; i < numRecords; ++i) { + byte[] record = + extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); + byte[] address = extractBytes(record, 0, 6); + reverse(address); + BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); + int rssi = record[8]; + long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); + results.add( + new ScanResult( + device, ScanRecord.parseFromBytes(new byte[0]), rssi, timestampNanos)); + } + return results; + } + + @VisibleForTesting + long parseTimestampNanos(byte[] data) { + long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); + // Timestamp is in every 50 ms. + return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); + } + + private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { + Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); + Set<ScanResult> results = new HashSet<ScanResult>(numRecords); + int position = 0; + long now = SystemClock.elapsedRealtimeNanos(); + while (position < batchRecord.length) { + byte[] address = extractBytes(batchRecord, position, 6); + // TODO: remove temp hack. + reverse(address); + BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); + position += 6; + // Skip address type. + position++; + // Skip tx power level. + position++; + int rssi = batchRecord[position++]; + long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); + position += 2; + + // Combine advertise packet and scan response packet. + int advertisePacketLen = batchRecord[position++]; + byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); + position += advertisePacketLen; + int scanResponsePacketLen = batchRecord[position++]; + byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); + position += scanResponsePacketLen; + byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; + System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); + System.arraycopy( + scanResponseBytes, 0, scanRecord, advertisePacketLen, scanResponsePacketLen); + Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); + results.add( + new ScanResult( + device, ScanRecord.parseFromBytes(scanRecord), rssi, timestampNanos)); + } + return results; + } + + // Reverse byte array. + private void reverse(byte[] address) { + int len = address.length; + for (int i = 0; i < len / 2; ++i) { + byte b = address[i]; + address[i] = address[len - 1 - i]; + address[len - 1 - i] = b; + } + } + + // Helper method to extract bytes from byte array. + private static byte[] extractBytes(byte[] scanRecord, int start, int length) { + byte[] bytes = new byte[length]; + System.arraycopy(scanRecord, start, bytes, 0, length); + return bytes; + } + + void onBatchScanThresholdCrossed(int clientIf) { + Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); + flushPendingBatchResultsInternal(clientIf); + } + + AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject( + int clientIf, + int advPktLen, + byte[] advPkt, + int scanRspLen, + byte[] scanRsp, + int filtIndex, + int advState, + int advInfoPresent, + String address, + int addrType, + int txPower, + int rssiValue, + int timeStamp) { + + return new AdvtFilterOnFoundOnLostInfo( + clientIf, + advPktLen, + advPkt, + scanRspLen, + scanRsp, + filtIndex, + advState, + advInfoPresent, + address, + addrType, + txPower, + rssiValue, + timeStamp); + } + + void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { + Log.d( + TAG, + "onTrackAdvFoundLost() - scannerId= " + + trackingInfo.getClientIf() + + " address = " + + trackingInfo.getAddress() + + " addressType = " + + trackingInfo.getAddressType() + + " adv_state = " + + trackingInfo.getAdvState()); + + ScannerMap.ScannerApp app = mScannerMap.getById(trackingInfo.getClientIf()); + if (app == null) { + Log.e(TAG, "app is null"); + return; + } + + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter() + .getRemoteLeDevice( + trackingInfo.getAddress(), trackingInfo.getAddressType()); + int advertiserState = trackingInfo.getAdvState(); + ScanResult result = + new ScanResult( + device, + ScanRecord.parseFromBytes(trackingInfo.getResult()), + trackingInfo.getRSSIValue(), + SystemClock.elapsedRealtimeNanos()); + + for (ScanClient client : mScanManager.getRegularScanQueue()) { + if (client.scannerId == trackingInfo.getClientIf()) { + ScanSettings settings = client.settings; + if ((advertiserState == ADVT_STATE_ONFOUND) + && ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) + != 0)) { + if (app.mCallback != null) { + app.mCallback.onFoundOrLost(true, result); + } else { + sendResultByPendingIntent( + app.mInfo, result, ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); + } + } else if ((advertiserState == ADVT_STATE_ONLOST) + && ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST) + != 0)) { + if (app.mCallback != null) { + app.mCallback.onFoundOrLost(false, result); + } else { + sendResultByPendingIntent( + app.mInfo, result, ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); + } + } else { + Log.d( + TAG, + "Not reporting onlost/onfound : " + + advertiserState + + " scannerId = " + + client.scannerId + + " callbackType " + + settings.getCallbackType()); + } + } + } + } + + /** Callback method for configuration of scan parameters. */ + void onScanParamSetupCompleted(int status, int scannerId) { + Log.d(TAG, "onScanParamSetupCompleted() - scannerId=" + scannerId + ", status=" + status); + ScannerMap.ScannerApp app = mScannerMap.getById(scannerId); + if (app == null || app.mCallback == null) { + Log.e(TAG, "Advertise app or callback is null"); + return; + } + } + + // callback from ScanManager for dispatch of errors apps. + void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { + ScannerMap.ScannerApp app = mScannerMap.getById(scannerId); + if (app == null) { + Log.e(TAG, "App null"); + return; + } + if (app.mCallback != null) { + app.mCallback.onScanManagerErrorCallback(errorCode); + } else { + try { + sendErrorByPendingIntent(app.mInfo, errorCode); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Error sending error code via PendingIntent:" + e); + } + } + } + + int msftMonitorHandleFromFilterIndex(int filterIndex) { + if (!mFilterIndexToMsftAdvMonitorMap.containsKey(filterIndex)) { + Log.e(TAG, "Monitor with filterIndex'" + filterIndex + "' does not exist"); + return -1; + } + return mFilterIndexToMsftAdvMonitorMap.get(filterIndex); + } + + void onMsftAdvMonitorAdd(int filterIndex, int monitorHandle, int status) { + if (status != 0) { + Log.e( + TAG, + "Error adding advertisement monitor with filter index '" + filterIndex + "'"); + return; + } + if (mFilterIndexToMsftAdvMonitorMap.containsKey(filterIndex)) { + Log.e(TAG, "Monitor with filterIndex'" + filterIndex + "' already added"); + return; + } + mFilterIndexToMsftAdvMonitorMap.put(filterIndex, monitorHandle); + } + + void onMsftAdvMonitorRemove(int filterIndex, int status) { + if (status != 0) { + Log.e( + TAG, + "Error removing advertisement monitor with filter index '" + filterIndex + "'"); + } + if (!mFilterIndexToMsftAdvMonitorMap.containsKey(filterIndex)) { + Log.e(TAG, "Monitor with filterIndex'" + filterIndex + "' does not exist"); + return; + } + mFilterIndexToMsftAdvMonitorMap.remove(filterIndex); + } + + void onMsftAdvMonitorEnable(int status) { + if (status != 0) { + Log.e(TAG, "Error enabling advertisement monitor"); + } + } + + /************************************************************************** + * GATT Service functions - Shared CLIENT/SERVER + *************************************************************************/ + + @RequiresPermission(BLUETOOTH_SCAN) + @VisibleForTesting + void registerScanner( + IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper registerScanner")) { + return; + } + + enforceImpersonatationPermissionIfNeeded(workSource); + + AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid()); + if (app != null + && app.isScanningTooFrequently() + && !Utils.checkCallerHasPrivilegedPermission(mAdapterService)) { + Log.e(TAG, "App '" + app.mAppName + "' is scanning too frequently"); + try { + callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); + } catch (RemoteException e) { + Log.e(TAG, "Exception: " + e); + } + return; + } + registerScannerInternal(callback, attributionSource, workSource); + } + + /** Intended for internal use within the Bluetooth app. Bypass permission check */ + public void registerScannerInternal( + IScannerCallback callback, AttributionSource attrSource, WorkSource workSource) { + UUID uuid = UUID.randomUUID(); + Log.d(TAG, "registerScanner() - UUID=" + uuid); + + mScannerMap.add(uuid, attrSource, workSource, callback, mAdapterService, this); + mScanManager.registerScanner(uuid); + } + + @RequiresPermission(BLUETOOTH_SCAN) + private void unregisterScanner(int scannerId, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper unregisterScanner")) { + return; + } + + unregisterScannerInternal(scannerId); + } + + /** Intended for internal use within the Bluetooth app. Bypass permission check */ + public void unregisterScannerInternal(int scannerId) { + Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); + mScannerMap.remove(scannerId); + mScanManager.unregisterScanner(scannerId); + } + + private List<String> getAssociatedDevices(String callingPackage) { + if (mCompanionManager == null) { + return Collections.emptyList(); + } + + final long identity = Binder.clearCallingIdentity(); + try { + return mCompanionManager.getAllAssociations().stream() + .filter( + info -> + info.getPackageName().equals(callingPackage) + && !info.isSelfManaged() + && info.getDeviceMacAddress() != null) + .map(AssociationInfo::getDeviceMacAddress) + .map(MacAddress::toString) + .collect(Collectors.toList()); + } catch (SecurityException se) { + // Not an app with associated devices + } catch (Exception e) { + Log.e(TAG, "Cannot check device associations for " + callingPackage, e); + } finally { + Binder.restoreCallingIdentity(identity); + } + return Collections.emptyList(); + } + + @RequiresPermission(BLUETOOTH_SCAN) + private void startScan( + int scannerId, + ScanSettings settings, + List<ScanFilter> filters, + AttributionSource attributionSource) { + Log.d(TAG, "start scan with filters"); + + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "Starting GATT scan.")) { + return; + } + + enforcePrivilegedPermissionIfNeeded(settings); + String callingPackage = attributionSource.getPackageName(); + settings = enforceReportDelayFloor(settings); + enforcePrivilegedPermissionIfNeeded(filters); + final ScanClient scanClient = new ScanClient(scannerId, settings, filters); + scanClient.userHandle = Binder.getCallingUserHandle(); + mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); + scanClient.eligibleForSanitizedExposureNotification = + callingPackage.equals(mExposureNotificationPackage); + + scanClient.hasDisavowedLocation = + Utils.hasDisavowedLocationForScan( + mAdapterService, attributionSource, mTestModeEnabled); + + scanClient.isQApp = + checkCallerTargetSdk(mAdapterService, callingPackage, Build.VERSION_CODES.Q); + if (!scanClient.hasDisavowedLocation) { + if (scanClient.isQApp) { + scanClient.hasLocationPermission = + Utils.checkCallerHasFineLocation( + mAdapterService, attributionSource, scanClient.userHandle); + } else { + scanClient.hasLocationPermission = + Utils.checkCallerHasCoarseOrFineLocation( + mAdapterService, attributionSource, scanClient.userHandle); + } + } + scanClient.hasNetworkSettingsPermission = + Utils.checkCallerHasNetworkSettingsPermission(mAdapterService); + scanClient.hasNetworkSetupWizardPermission = + Utils.checkCallerHasNetworkSetupWizardPermission(mAdapterService); + scanClient.hasScanWithoutLocationPermission = + Utils.checkCallerHasScanWithoutLocationPermission(mAdapterService); + scanClient.associatedDevices = getAssociatedDevices(callingPackage); + + startScan(scannerId, settings, filters, scanClient); + } + + /** Intended for internal use within the Bluetooth app. Bypass permission check */ + public void startScanInternal(int scannerId, ScanSettings settings, List<ScanFilter> filters) { + final ScanClient scanClient = new ScanClient(scannerId, settings, filters); + scanClient.userHandle = Binder.getCallingUserHandle(); + scanClient.eligibleForSanitizedExposureNotification = false; + scanClient.hasDisavowedLocation = false; + scanClient.isQApp = true; + scanClient.hasNetworkSettingsPermission = + Utils.checkCallerHasNetworkSettingsPermission(mAdapterService); + scanClient.hasNetworkSetupWizardPermission = + Utils.checkCallerHasNetworkSetupWizardPermission(mAdapterService); + scanClient.hasScanWithoutLocationPermission = + Utils.checkCallerHasScanWithoutLocationPermission(mAdapterService); + scanClient.associatedDevices = Collections.emptyList(); + + startScan(scannerId, settings, filters, scanClient); + } + + private void startScan( + int scannerId, ScanSettings settings, List<ScanFilter> filters, ScanClient scanClient) { + AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); + if (app != null) { + scanClient.stats = app; + boolean isFilteredScan = (filters != null) && !filters.isEmpty(); + boolean isCallbackScan = false; + + ScannerMap.ScannerApp cbApp = mScannerMap.getById(scannerId); + if (cbApp != null) { + isCallbackScan = cbApp.mCallback != null; + } + app.recordScanStart( + settings, + filters, + isFilteredScan, + isCallbackScan, + scannerId, + cbApp == null ? null : cbApp.mAttributionTag); + } + + mScanManager.startScan(scanClient); + } + + @RequiresPermission(BLUETOOTH_SCAN) + private void registerPiAndStartScan( + PendingIntent pendingIntent, + ScanSettings settings, + List<ScanFilter> filters, + AttributionSource attributionSource) { + Log.d(TAG, "start scan with filters, for PendingIntent"); + + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "Starting GATT scan.")) { + return; + } + enforcePrivilegedPermissionIfNeeded(settings); + settings = enforceReportDelayFloor(settings); + enforcePrivilegedPermissionIfNeeded(filters); + UUID uuid = UUID.randomUUID(); + String callingPackage = attributionSource.getPackageName(); + int callingUid = attributionSource.getUid(); + PendingIntentInfo piInfo = new PendingIntentInfo(); + piInfo.intent = pendingIntent; + piInfo.settings = settings; + piInfo.filters = filters; + piInfo.callingPackage = callingPackage; + piInfo.callingUid = callingUid; + Log.d( + TAG, + "startScan(PI) -" + + (" UUID=" + uuid) + + (" Package=" + callingPackage) + + (" UID=" + callingUid)); + + // Don't start scan if the Pi scan already in mScannerMap. + if (mScannerMap.getByPendingIntentInfo(piInfo) != null) { + Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap."); + return; + } + + ScannerMap.ScannerApp app = + mScannerMap.add(uuid, attributionSource, piInfo, mAdapterService, this); + + app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); + mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); + app.mEligibleForSanitizedExposureNotification = + callingPackage.equals(mExposureNotificationPackage); + + app.mHasDisavowedLocation = + Utils.hasDisavowedLocationForScan( + mAdapterService, attributionSource, mTestModeEnabled); + + if (!app.mHasDisavowedLocation) { + try { + if (checkCallerTargetSdk(mAdapterService, callingPackage, Build.VERSION_CODES.Q)) { + app.mHasLocationPermission = + Utils.checkCallerHasFineLocation( + mAdapterService, attributionSource, app.mUserHandle); + } else { + app.mHasLocationPermission = + Utils.checkCallerHasCoarseOrFineLocation( + mAdapterService, attributionSource, app.mUserHandle); + } + } catch (SecurityException se) { + // No need to throw here. Just mark as not granted. + app.mHasLocationPermission = false; + } + } + app.mHasNetworkSettingsPermission = + Utils.checkCallerHasNetworkSettingsPermission(mAdapterService); + app.mHasNetworkSetupWizardPermission = + Utils.checkCallerHasNetworkSetupWizardPermission(mAdapterService); + app.mHasScanWithoutLocationPermission = + Utils.checkCallerHasScanWithoutLocationPermission(mAdapterService); + app.mAssociatedDevices = getAssociatedDevices(callingPackage); + mScanManager.registerScanner(uuid); + + // If this fails, we should stop the scan immediately. + if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) { + Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan."); + stopScan(pendingIntent, attributionSource); + } + } + + /** Start a scan with pending intent. */ + @VisibleForTesting + void continuePiStartScan(int scannerId, ScannerMap.ScannerApp app) { + final PendingIntentInfo piInfo = app.mInfo; + final ScanClient scanClient = + new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.callingUid); + scanClient.hasLocationPermission = app.mHasLocationPermission; + scanClient.userHandle = app.mUserHandle; + scanClient.isQApp = checkCallerTargetSdk(mAdapterService, app.mName, Build.VERSION_CODES.Q); + scanClient.eligibleForSanitizedExposureNotification = + app.mEligibleForSanitizedExposureNotification; + scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission; + scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission; + scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission; + scanClient.associatedDevices = app.mAssociatedDevices; + scanClient.hasDisavowedLocation = app.mHasDisavowedLocation; + + AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId); + if (scanStats != null) { + scanClient.stats = scanStats; + boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); + scanStats.recordScanStart( + piInfo.settings, + piInfo.filters, + isFilteredScan, + false, + scannerId, + app.mAttributionTag); + } + + mScanManager.startScan(scanClient); + } + + @RequiresPermission(BLUETOOTH_SCAN) + @VisibleForTesting + void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper flushPendingBatchResults")) { + return; + } + flushPendingBatchResultsInternal(scannerId); + } + + private void flushPendingBatchResultsInternal(int scannerId) { + Log.d(TAG, "flushPendingBatchResultsInternal - scannerId=" + scannerId); + mScanManager.flushBatchScanResults(new ScanClient(scannerId)); + } + + @RequiresPermission(BLUETOOTH_SCAN) + private void stopScan(int scannerId, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper stopScan")) { + return; + } + stopScanInternal(scannerId); + } + + /** Intended for internal use within the Bluetooth app. Bypass permission check */ + public void stopScanInternal(int scannerId) { + int scanQueueSize = + mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size(); + Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); + + AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); + if (app != null) { + app.recordScanStop(scannerId); + } + + mScanManager.stopScan(scannerId); + } + + @RequiresPermission(BLUETOOTH_SCAN) + private void stopScan(PendingIntent intent, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper stopScan")) { + return; + } + stopScanInternal(intent); + } + + /** Intended for internal use within the Bluetooth app. Bypass permission check */ + private void stopScanInternal(PendingIntent intent) { + PendingIntentInfo pii = new PendingIntentInfo(); + pii.intent = intent; + ScannerMap.ScannerApp app = mScannerMap.getByPendingIntentInfo(pii); + Log.v(TAG, "stopScan(PendingIntent): app found = " + app); + if (app != null) { + intent.removeCancelListener(mScanIntentCancelListener); + final int scannerId = app.mId; + stopScanInternal(scannerId); + // Also unregister the scanner + unregisterScannerInternal(scannerId); + } + } + + /************************************************************************** + * PERIODIC SCANNING + *************************************************************************/ + @RequiresPermission(BLUETOOTH_SCAN) + @VisibleForTesting + void registerSync( + ScanResult scanResult, + int skip, + int timeout, + IPeriodicAdvertisingCallback callback, + AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper registerSync")) { + return; + } + mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); + } + + @RequiresPermission(BLUETOOTH_SCAN) + @VisibleForTesting + void unregisterSync( + IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper unregisterSync")) { + return; + } + mPeriodicScanManager.stopSync(callback); + } + + @RequiresPermission(BLUETOOTH_SCAN) + @VisibleForTesting + void transferSync( + BluetoothDevice bda, + int serviceData, + int syncHandle, + AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper transferSync")) { + return; + } + mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); + } + + @RequiresPermission(BLUETOOTH_SCAN) + @VisibleForTesting + void transferSetInfo( + BluetoothDevice bda, + int serviceData, + int advHandle, + IPeriodicAdvertisingCallback callback, + AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper transferSetInfo")) { + return; + } + mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); + } + + @RequiresPermission(BLUETOOTH_SCAN) + private int numHwTrackFiltersAvailable(AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mAdapterService, attributionSource, "ScanHelper numHwTrackFiltersAvailable")) { + return 0; + } + return (mAdapterService.getTotalNumOfTrackableAdvertisements() + - mScanManager.getCurrentUsedTrackingAdvertisement()); + } + + /** + * DeathRecipient handler used to unregister applications that disconnect ungracefully (ie. + * crash or forced close). + */ + class ScannerDeathRecipient implements IBinder.DeathRecipient { + int mScannerId; + private String mPackageName; + + ScannerDeathRecipient(int scannerId, String packageName) { + mScannerId = scannerId; + mPackageName = packageName; + } + + @Override + public void binderDied() { + Log.d( + TAG, + "Binder is dead - unregistering scanner (" + + mPackageName + + " " + + mScannerId + + ")!"); + + ScanClient client = getScanClient(mScannerId); + if (client != null) { + handleDeadScanClient(client); + } + } + + private ScanClient getScanClient(int clientIf) { + for (ScanClient client : mScanManager.getRegularScanQueue()) { + if (client.scannerId == clientIf) { + return client; + } + } + for (ScanClient client : mScanManager.getBatchScanQueue()) { + if (client.scannerId == clientIf) { + return client; + } + } + return null; + } + } + + private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { + // BLE scan only mode needs special permission. + if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) { + return true; + } + + // Regular scan, no special permission. + if (settings == null) { + return false; + } + + // Ambient discovery mode, needs privileged permission. + if (settings.getScanMode() == ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY) { + return true; + } + + // Regular scan, no special permission. + if (settings.getReportDelayMillis() == 0) { + return false; + } + + // Batch scan, truncated mode needs permission. + return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; + } + + /* + * The ScanFilter#setDeviceAddress API overloads are @SystemApi access methods. This + * requires that the permissions be BLUETOOTH_PRIVILEGED. + */ + @SuppressLint("AndroidFrameworkRequiresPermission") + private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) { + Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")"); + // Some 3p API cases may have null filters, need to allow + if (filters != null) { + for (ScanFilter filter : filters) { + // The only case to enforce here is if there is an address + // If there is an address, enforce if the correct combination criteria is met. + if (filter.getDeviceAddress() != null) { + // At this point we have an address, that means a caller used the + // setDeviceAddress(address) public API for the ScanFilter + // We don't want to enforce if the type is PUBLIC and the IRK is null + // However, if we have a different type that means the caller used a new + // @SystemApi such as setDeviceAddress(address, type) or + // setDeviceAddress(address, type, irk) which are both @SystemApi and require + // permissions to be enforced + if (filter.getAddressType() == BluetoothDevice.ADDRESS_TYPE_PUBLIC + && filter.getIrk() == null) { + // Do not enforce + } else { + mAdapterService.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + } + } + } + } + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { + if (needsPrivilegedPermissionForScan(settings)) { + mAdapterService.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + } + } + + // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other + // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does + // not have UPDATE_DEVICE_STATS permission. + @RequiresPermission(UPDATE_DEVICE_STATS) + private void enforceImpersonatationPermission() { + mAdapterService.enforceCallingOrSelfPermission( + UPDATE_DEVICE_STATS, "Need UPDATE_DEVICE_STATS permission"); + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private void enforceImpersonatationPermissionIfNeeded(WorkSource workSource) { + if (workSource != null) { + enforceImpersonatationPermission(); + } + } + + /** + * Ensures the report delay is either 0 or at least the floor value (5000ms) + * + * @param settings are the scan settings passed into a request to start le scanning + * @return the passed in ScanSettings object if the report delay is 0 or above the floor value; + * a new ScanSettings object with the report delay being the floor value if the original + * report delay was between 0 and the floor value (exclusive of both) + */ + @VisibleForTesting + ScanSettings enforceReportDelayFloor(ScanSettings settings) { + if (settings.getReportDelayMillis() == 0) { + return settings; + } + + // Need to clear identity to pass device config permission check + final long callerToken = Binder.clearCallingIdentity(); + try { + long floor = + DeviceConfig.getLong( + DeviceConfig.NAMESPACE_BLUETOOTH, + "report_delay", + DEFAULT_REPORT_DELAY_FLOOR); + + if (settings.getReportDelayMillis() > floor) { + return settings; + } else { + return new ScanSettings.Builder() + .setCallbackType(settings.getCallbackType()) + .setLegacy(settings.getLegacy()) + .setMatchMode(settings.getMatchMode()) + .setNumOfMatches(settings.getNumOfMatches()) + .setPhy(settings.getPhy()) + .setReportDelay(floor) + .setScanMode(settings.getScanMode()) + .setScanResultType(settings.getScanResultType()) + .build(); + } + } finally { + Binder.restoreCallingIdentity(callerToken); + } + } + + void addScanEvent(BluetoothMetricsProto.ScanEvent event) { + synchronized (mScanEvents) { + if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { + mScanEvents.remove(); + } + mScanEvents.add(event); + } + } + public void dumpRegisterId(StringBuilder sb) { sb.append(" Scanner:\n"); - mTransitionalScanHelper.getScannerMap().dumpApps(sb, ProfileService::println); + mScannerMap.dumpApps(sb, ProfileService::println); } public void dump(StringBuilder sb) { sb.append("GATT Scanner Map\n"); - mTransitionalScanHelper.getScannerMap().dump(sb); + mScannerMap.dump(sb); } public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { - mTransitionalScanHelper.dumpProto(builder); + synchronized (mScanEvents) { + builder.addAllScanEvent(mScanEvents); + } } static class BluetoothScanBinder extends IBluetoothScan.Stub { @@ -172,7 +1743,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .registerScanner(callback, workSource, attributionSource); } @@ -183,7 +1753,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .unregisterScanner(scannerId, attributionSource); } @@ -198,7 +1767,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .startScan(scannerId, settings, filters, attributionSource); } @@ -213,7 +1781,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .registerPiAndStartScan(intent, settings, filters, attributionSource); } @@ -223,7 +1790,7 @@ public class ScanController { if (mScanController == null) { return; } - mScanController.getTransitionalScanHelper().stopScan(scannerId, attributionSource); + mScanController.stopScan(scannerId, attributionSource); } @Override @@ -232,7 +1799,7 @@ public class ScanController { if (mScanController == null) { return; } - mScanController.getTransitionalScanHelper().stopScan(intent, attributionSource); + mScanController.stopScan(intent, attributionSource); } @Override @@ -242,7 +1809,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .flushPendingBatchResults(scannerId, attributionSource); } @@ -258,7 +1824,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .registerSync(scanResult, skip, timeout, callback, attributionSource); } @@ -269,7 +1834,7 @@ public class ScanController { if (mScanController == null) { return; } - mScanController.getTransitionalScanHelper().unregisterSync(callback, attributionSource); + mScanController.unregisterSync(callback, attributionSource); } @Override @@ -283,7 +1848,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .transferSync(bda, serviceData, syncHandle, attributionSource); } @@ -299,7 +1863,6 @@ public class ScanController { return; } mScanController - .getTransitionalScanHelper() .transferSetInfo(bda, serviceData, advHandle, callback, attributionSource); } @@ -310,7 +1873,6 @@ public class ScanController { return 0; } return mScanController - .getTransitionalScanHelper() .numHwTrackFiltersAvailable(attributionSource); } diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java index 453b5849fd..b228bf5fc8 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java @@ -85,7 +85,7 @@ public class ScanManager { public static final int SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS = 183; public static final int SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS = 730; - // Result type defined in bt stack. Need to be accessed by TransitionalScanHelper. + // Result type defined in bt stack. Need to be accessed by ScanController. static final int SCAN_RESULT_TYPE_TRUNCATED = 1; static final int SCAN_RESULT_TYPE_FULL = 2; static final int SCAN_RESULT_TYPE_BOTH = 3; @@ -119,7 +119,7 @@ public class ScanManager { @GuardedBy("mCurUsedTrackableAdvertisementsLock") private int mCurUsedTrackableAdvertisements = 0; - private final TransitionalScanHelper mScanHelper; + private final ScanController mScanController; private final AdapterService mAdapterService; private final TimeProvider mTimeProvider; private ScanNative mScanNative; @@ -160,7 +160,7 @@ public class ScanManager { public ScanManager( AdapterService adapterService, - TransitionalScanHelper scanHelper, + ScanController scanController, BluetoothAdapterProxy bluetoothAdapterProxy, Looper looper, TimeProvider timeProvider) { @@ -169,10 +169,10 @@ public class ScanManager { mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mSuspendedScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); - mScanHelper = scanHelper; + mScanController = scanController; mAdapterService = adapterService; mTimeProvider = timeProvider; - mScanNative = new ScanNative(scanHelper); + mScanNative = new ScanNative(scanController); mDisplayManager = mAdapterService.getSystemService(DisplayManager.class); mActivityManager = mAdapterService.getSystemService(ActivityManager.class); mLocationManager = mAdapterService.getSystemService(LocationManager.class); @@ -492,7 +492,7 @@ public class ScanManager { } if (client.appDied) { Log.d(TAG, "app died, unregister scanner - " + client.scannerId); - mScanHelper.unregisterScannerInternal(client.scannerId); + mScanController.unregisterScannerInternal(client.scannerId); } } @@ -1010,9 +1010,9 @@ public class ScanManager { private final MsftAdvMonitorMergedPatternList mMsftAdvMonitorMergedPatternList = new MsftAdvMonitorMergedPatternList(); - ScanNative(TransitionalScanHelper scanHelper) { + ScanNative(ScanController scanController) { mNativeInterface = ScanObjectsFactory.getInstance().getScanNativeInterface(); - mNativeInterface.init(scanHelper); + mNativeInterface.init(scanController); mFilterIndexStack = new ArrayDeque<Integer>(); mClientFilterIndexMap = new HashMap<Integer, Deque<Integer>>(); @@ -1386,7 +1386,7 @@ public class ScanManager { "Error freeing for onfound/onlost filter resources " + entriesToFreePerFilter); try { - mScanHelper.onScanManagerErrorCallback( + mScanController.onScanManagerErrorCallback( client.scannerId, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } catch (RemoteException e) { Log.e(TAG, "failed on onScanManagerCallback at freeing", e); @@ -1587,7 +1587,7 @@ public class ScanManager { mAdapterService.getTotalNumOfTrackableAdvertisements()); } try { - mScanHelper.onScanManagerErrorCallback( + mScanController.onScanManagerErrorCallback( scannerId, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } catch (RemoteException e) { Log.e(TAG, "failed on onScanManagerCallback", e); @@ -2113,7 +2113,7 @@ public class ScanManager { new ActivityManager.OnUidImportanceListener() { @Override public void onUidImportance(final int uid, final int importance) { - if (mScanHelper.getScannerMap().getAppScanStatsByUid(uid) != null) { + if (mScanController.getScannerMap().getAppScanStatsByUid(uid) != null) { Message message = new Message(); message.what = MSG_IMPORTANCE_CHANGE; message.obj = new UidImportance(uid, importance); diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java index 9f0ebcc979..1b14b7e500 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java @@ -33,7 +33,7 @@ public class ScanNativeInterface { private static ScanNativeInterface sInterface; private CountDownLatch mLatch = new CountDownLatch(1); - @Nullable private TransitionalScanHelper mScanHelper; + @Nullable private ScanController mScanController; private ScanNativeInterface() {} @@ -59,8 +59,8 @@ public class ScanNativeInterface { } } - void init(TransitionalScanHelper scanHelper) { - mScanHelper = scanHelper; + void init(ScanController scanController) { + mScanController = scanController; initializeNative(); } @@ -202,7 +202,7 @@ public class ScanNativeInterface { /** Remove a MSFT Advertisement Monitor */ public void gattClientMsftAdvMonitorRemove(int filter_index) { - int monitor_handle = mScanHelper.msftMonitorHandleFromFilterIndex(filter_index); + int monitor_handle = mScanController.msftMonitorHandleFromFilterIndex(filter_index); if (monitor_handle < 0) return; gattClientMsftAdvMonitorRemoveNative(filter_index, monitor_handle); } @@ -278,11 +278,11 @@ public class ScanNativeInterface { int periodicAdvInt, byte[] advData, String originalAddress) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onScanResult( + mScanController.onScanResult( eventType, addressType, address, @@ -298,70 +298,70 @@ public class ScanNativeInterface { void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) throws RemoteException { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onScannerRegistered(status, scannerId, uuidLsb, uuidMsb); + mScanController.onScannerRegistered(status, scannerId, uuidLsb, uuidMsb); } void onScanFilterEnableDisabled(int action, int status, int clientIf) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onScanFilterEnableDisabled(action, status, clientIf); + mScanController.onScanFilterEnableDisabled(action, status, clientIf); } void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onScanFilterParamsConfigured(action, status, clientIf, availableSpace); + mScanController.onScanFilterParamsConfigured(action, status, clientIf, availableSpace); } void onScanFilterConfig( int action, int status, int clientIf, int filterType, int availableSpace) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onScanFilterConfig(action, status, clientIf, filterType, availableSpace); + mScanController.onScanFilterConfig(action, status, clientIf, filterType, availableSpace); } void onBatchScanStorageConfigured(int status, int clientIf) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onBatchScanStorageConfigured(status, clientIf); + mScanController.onBatchScanStorageConfigured(status, clientIf); } void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onBatchScanStartStopped(startStopAction, status, clientIf); + mScanController.onBatchScanStartStopped(startStopAction, status, clientIf); } void onBatchScanReports( int status, int scannerId, int reportType, int numRecords, byte[] recordData) throws RemoteException { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onBatchScanReports(status, scannerId, reportType, numRecords, recordData); + mScanController.onBatchScanReports(status, scannerId, reportType, numRecords, recordData); } void onBatchScanThresholdCrossed(int clientIf) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onBatchScanThresholdCrossed(clientIf); + mScanController.onBatchScanThresholdCrossed(clientIf); } @Nullable @@ -379,11 +379,11 @@ public class ScanNativeInterface { int txPower, int rssiValue, int timeStamp) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return null; } - return mScanHelper.createOnTrackAdvFoundLostObject( + return mScanController.createOnTrackAdvFoundLostObject( clientIf, advPktLen, advPkt, @@ -400,42 +400,42 @@ public class ScanNativeInterface { } void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onTrackAdvFoundLost(trackingInfo); + mScanController.onTrackAdvFoundLost(trackingInfo); } void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onScanParamSetupCompleted(status, scannerId); + mScanController.onScanParamSetupCompleted(status, scannerId); } void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onMsftAdvMonitorAdd(filter_index, monitor_handle, status); + mScanController.onMsftAdvMonitorAdd(filter_index, monitor_handle, status); } void onMsftAdvMonitorRemove(int filter_index, int status) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onMsftAdvMonitorRemove(filter_index, status); + mScanController.onMsftAdvMonitorRemove(filter_index, status); } void onMsftAdvMonitorEnable(int status) { - if (mScanHelper == null) { + if (mScanController == null) { Log.e(TAG, "Scan helper is null!"); return; } - mScanHelper.onMsftAdvMonitorEnable(status); + mScanController.onMsftAdvMonitorEnable(status); } } diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java b/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java index f3fba49c79..3d5521786c 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java @@ -68,18 +68,18 @@ public class ScanObjectsFactory { * Create an instance of ScanManager * * @param adapterService an AdapterService instance - * @param scanHelper a TransitionalScanHelper instance + * @param scanController a ScanController instance * @param bluetoothAdapterProxy a bluetoothAdapterProxy instance * @param looper the looper to be used for processing messages * @return the created ScanManager instance */ public ScanManager createScanManager( AdapterService adapterService, - TransitionalScanHelper scanHelper, + ScanController scanController, BluetoothAdapterProxy bluetoothAdapterProxy, Looper looper) { return new ScanManager( - adapterService, scanHelper, bluetoothAdapterProxy, looper, getSystemClock()); + adapterService, scanController, bluetoothAdapterProxy, looper, getSystemClock()); } public PeriodicScanManager createPeriodicScanManager(AdapterService adapterService) { diff --git a/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java b/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java index 00d9641032..a31f6b1c75 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java @@ -56,18 +56,25 @@ public class ScannerMap { WorkSource workSource, IScannerCallback callback, AdapterService adapterService, - TransitionalScanHelper scanHelper) { - return add(uuid, attributionSource, workSource, callback, null, adapterService, scanHelper); + ScanController scanController) { + return add( + uuid, + attributionSource, + workSource, + callback, + null, + adapterService, + scanController); } /** Add an entry to the application context list with a pending intent. */ ScannerApp add( UUID uuid, AttributionSource attributionSource, - TransitionalScanHelper.PendingIntentInfo piInfo, + ScanController.PendingIntentInfo piInfo, AdapterService adapterService, - TransitionalScanHelper scanHelper) { - return add(uuid, attributionSource, null, null, piInfo, adapterService, scanHelper); + ScanController scanController) { + return add(uuid, attributionSource, null, null, piInfo, adapterService, scanController); } private ScannerApp add( @@ -75,9 +82,9 @@ public class ScannerMap { AttributionSource attributionSource, @Nullable WorkSource workSource, @Nullable IScannerCallback callback, - @Nullable TransitionalScanHelper.PendingIntentInfo piInfo, + @Nullable ScanController.PendingIntentInfo piInfo, AdapterService adapterService, - TransitionalScanHelper scanHelper) { + ScanController scanController) { int appUid; String appName = null; if (piInfo != null) { @@ -99,7 +106,7 @@ public class ScannerMap { workSource, this, adapterService, - scanHelper, + scanController, getSystemClock()); mAppScanStatsMap.put(appUid, appScanStats); } @@ -175,7 +182,7 @@ public class ScannerMap { } /** Get an application context by the pending intent info object. */ - ScannerApp getByPendingIntentInfo(TransitionalScanHelper.PendingIntentInfo info) { + ScannerApp getByPendingIntentInfo(ScanController.PendingIntentInfo info) { ScannerApp app = getAppByPredicate(entry -> entry.mInfo != null && entry.mInfo.equals(info)); if (app == null) { @@ -219,7 +226,7 @@ public class ScannerMap { public static class ScannerApp { /** Context information */ - @Nullable TransitionalScanHelper.PendingIntentInfo mInfo; + @Nullable ScanController.PendingIntentInfo mInfo; /** Statistics for this app */ AppScanStats mAppScanStats; @@ -269,7 +276,7 @@ public class ScannerMap { UUID uuid, @Nullable String attributionTag, @Nullable IScannerCallback callback, - @Nullable TransitionalScanHelper.PendingIntentInfo info, + @Nullable ScanController.PendingIntentInfo info, String name, AppScanStats appScanStats) { this.mUuid = uuid; diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java deleted file mode 100644 index 102d0d0649..0000000000 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ /dev/null @@ -1,1674 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.bluetooth.le_scan; - -import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; -import static android.Manifest.permission.BLUETOOTH_SCAN; -import static android.Manifest.permission.UPDATE_DEVICE_STATS; - -import static com.android.bluetooth.Utils.checkCallerTargetSdk; - -import static java.util.Objects.requireNonNull; - -import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; -import android.app.AppOpsManager; -import android.app.PendingIntent; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothUtils; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.IPeriodicAdvertisingCallback; -import android.bluetooth.le.IScannerCallback; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.companion.AssociationInfo; -import android.companion.CompanionDeviceManager; -import android.content.AttributionSource; -import android.content.Intent; -import android.net.MacAddress; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.os.SystemClock; -import android.os.UserHandle; -import android.os.WorkSource; -import android.provider.DeviceConfig; -import android.util.Log; - -import com.android.bluetooth.BluetoothMetricsProto; -import com.android.bluetooth.R; -import com.android.bluetooth.Utils; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.BluetoothAdapterProxy; -import com.android.bluetooth.gatt.GattServiceConfig; -import com.android.bluetooth.util.NumberUtils; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * A helper class which contains all scan related functions extracted from {@link - * com.android.bluetooth.gatt.GattService}. The purpose of this class is to preserve scan - * functionality within GattService and provide the same functionality in {@link ScanController}. - */ -public class TransitionalScanHelper { - private static final String TAG = GattServiceConfig.TAG_PREFIX + "ScanHelper"; - - // Batch scan related constants. - private static final int TRUNCATED_RESULT_SIZE = 11; - - /** The default floor value for LE batch scan report delays greater than 0 */ - @VisibleForTesting static final long DEFAULT_REPORT_DELAY_FLOOR = 5000; - - private static final int NUM_SCAN_EVENTS_KEPT = 20; - - // onFoundLost related constants - @VisibleForTesting static final int ADVT_STATE_ONFOUND = 0; - private static final int ADVT_STATE_ONLOST = 1; - - private static final int ET_LEGACY_MASK = 0x10; - - /** Keep the arguments passed in for the PendingIntent. */ - public static class PendingIntentInfo { - public PendingIntent intent; - public ScanSettings settings; - public List<ScanFilter> filters; - public String callingPackage; - public int callingUid; - - @Override - public boolean equals(Object other) { - if (!(other instanceof PendingIntentInfo)) { - return false; - } - return intent.equals(((PendingIntentInfo) other).intent); - } - - @Override - public int hashCode() { - return intent == null ? 0 : intent.hashCode(); - } - } - - public interface TestModeAccessor { - /** Indicates if bluetooth test mode is enabled. */ - boolean isTestModeEnabled(); - } - - private final PendingIntent.CancelListener mScanIntentCancelListener = - new PendingIntent.CancelListener() { - public void onCanceled(PendingIntent intent) { - Log.d(TAG, "scanning PendingIntent canceled"); - stopScanInternal(intent); - } - }; - - private final AdapterService mAdapterService; - private final TestModeAccessor mTestModeAccessor; - private final HashMap<Integer, Integer> mFilterIndexToMsftAdvMonitorMap = new HashMap<>(); - private final String mExposureNotificationPackage; - - private AppOpsManager mAppOps; - private CompanionDeviceManager mCompanionManager; - private PeriodicScanManager mPeriodicScanManager; - private ScanManager mScanManager; - - private ScannerMap mScannerMap = new ScannerMap(); - - public ScannerMap getScannerMap() { - return mScannerMap; - } - - @VisibleForTesting - public void setScannerMap(ScannerMap scannerMap) { - mScannerMap = scannerMap; - } - - /** Internal list of scan events to use with the proto */ - private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents = - new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); - - private final Predicate<ScanResult> mLocationDenylistPredicate; - - public TransitionalScanHelper( - AdapterService adapterService, TestModeAccessor testModeAccessor) { - mAdapterService = requireNonNull(adapterService); - mExposureNotificationPackage = - mAdapterService.getString(R.string.exposure_notification_package); - mTestModeAccessor = testModeAccessor; - mLocationDenylistPredicate = - (scanResult) -> { - final MacAddress parsedAddress = - MacAddress.fromString(scanResult.getDevice().getAddress()); - if (mAdapterService - .getLocationDenylistMac() - .test(parsedAddress.toByteArray())) { - Log.v(TAG, "Skipping device matching denylist: " + scanResult.getDevice()); - return true; - } - final ScanRecord scanRecord = scanResult.getScanRecord(); - if (scanRecord.matchesAnyField( - mAdapterService.getLocationDenylistAdvertisingData())) { - Log.v(TAG, "Skipping data matching denylist: " + scanRecord); - return true; - } - return false; - }; - } - - /** - * Starts the LE scanning component. - * - * @param looper for scan operations - */ - public void start(Looper looper) { - mAppOps = mAdapterService.getSystemService(AppOpsManager.class); - mCompanionManager = mAdapterService.getSystemService(CompanionDeviceManager.class); - mScanManager = - ScanObjectsFactory.getInstance() - .createScanManager( - mAdapterService, - this, - BluetoothAdapterProxy.getInstance(), - looper); - - mPeriodicScanManager = - ScanObjectsFactory.getInstance().createPeriodicScanManager(mAdapterService); - } - - /** Stops the scanning component. */ - public void stop() { - mScannerMap.clear(); - } - - /** Cleans up the scanning component. */ - public void cleanup() { - if (mScanManager != null) { - mScanManager.cleanup(); - } - if (mPeriodicScanManager != null) { - mPeriodicScanManager.cleanup(); - } - } - - /** Notifies scan manager of bluetooth profile connection state changes */ - public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { - if (mScanManager == null) { - Log.w(TAG, "scan manager is null"); - return; - } - mScanManager.handleBluetoothProfileConnectionStateChanged(profile, fromState, toState); - } - - public int getCurrentUsedTrackingAdvertisement() { - return mScanManager.getCurrentUsedTrackingAdvertisement(); - } - - /************************************************************************** - * Callback functions - CLIENT - *************************************************************************/ - - // EN format defined here: - // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf - private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = - new byte[] { - // size 2, flag field, flags byte (value is not important) - (byte) 0x02, (byte) 0x01 - }; - - private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1; - private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = - new byte[] { - // size 3, complete 16 bit UUID, EN UUID - (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD, - // size 23, data for 16 bit UUID, EN UUID - (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD, - // ...payload - }; - private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2; - - private static boolean arrayStartsWith(byte[] array, byte[] prefix) { - if (array.length < prefix.length) { - return false; - } - for (int i = 0; i < prefix.length; i++) { - if (prefix[i] != array[i]) { - return false; - } - } - return true; - } - - private ScanResult getSanitizedExposureNotification(ScanResult result) { - ScanRecord record = result.getScanRecord(); - // Remove the flags part of the payload, if present - if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH - && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) { - record = - ScanRecord.parseFromBytes( - Arrays.copyOfRange( - record.getBytes(), - EXPOSURE_NOTIFICATION_FLAGS_LENGTH, - record.getBytes().length)); - } - - if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) { - return null; - } - if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) { - return null; - } - - return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0); - } - - /** Callback method for a scan result. */ - public void onScanResult( - int eventType, - int addressType, - String address, - int primaryPhy, - int secondaryPhy, - int advertisingSid, - int txPower, - int rssi, - int periodicAdvInt, - byte[] advData, - String originalAddress) { - // When in testing mode, ignore all real-world events - if (mTestModeAccessor.isTestModeEnabled()) return; - - AppScanStats.recordScanRadioResultCount(); - onScanResultInternal( - eventType, - addressType, - address, - primaryPhy, - secondaryPhy, - advertisingSid, - txPower, - rssi, - periodicAdvInt, - advData, - originalAddress); - } - - // TODO(b/327849650): Refactor to reduce the visibility of this method. - public void onScanResultInternal( - int eventType, - int addressType, - String address, - int primaryPhy, - int secondaryPhy, - int advertisingSid, - int txPower, - int rssi, - int periodicAdvInt, - byte[] advData, - String originalAddress) { - Log.v( - TAG, - "onScanResult() - eventType=0x" - + Integer.toHexString(eventType) - + ", addressType=" - + addressType - + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) - + ", primaryPhy=" - + primaryPhy - + ", secondaryPhy=" - + secondaryPhy - + ", advertisingSid=0x" - + Integer.toHexString(advertisingSid) - + ", txPower=" - + txPower - + ", rssi=" - + rssi - + ", periodicAdvInt=0x" - + Integer.toHexString(periodicAdvInt) - + ", originalAddress=" - + originalAddress); - - String identityAddress = mAdapterService.getIdentityAddress(address); - if (!address.equals(identityAddress)) { - Log.v( - TAG, - "found identityAddress of " - + address - + ", replace originalAddress as " - + identityAddress); - originalAddress = identityAddress; - } - - byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62); - - for (ScanClient client : mScanManager.getRegularScanQueue()) { - ScannerMap.ScannerApp app = mScannerMap.getById(client.scannerId); - if (app == null) { - Log.v(TAG, "App is null; skip."); - continue; - } - - BluetoothDevice device = - BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(address, addressType); - - ScanSettings settings = client.settings; - byte[] scanRecordData; - // This is for compatibility with applications that assume fixed size scan data. - if (settings.getLegacy()) { - if ((eventType & ET_LEGACY_MASK) == 0) { - // If this is legacy scan, but nonlegacy result - skip. - Log.v(TAG, "Legacy scan, non legacy result; skip."); - continue; - } else { - // Some apps are used to fixed-size advertise data. - scanRecordData = legacyAdvData; - } - } else { - scanRecordData = advData; - } - - ScanRecord scanRecord = ScanRecord.parseFromBytes(scanRecordData); - ScanResult result = - new ScanResult( - device, - eventType, - primaryPhy, - secondaryPhy, - advertisingSid, - txPower, - rssi, - periodicAdvInt, - scanRecord, - SystemClock.elapsedRealtimeNanos()); - - if (client.hasDisavowedLocation) { - if (mLocationDenylistPredicate.test(result)) { - Log.i(TAG, "Skipping client for location deny list"); - continue; - } - } - - boolean hasPermission = hasScanResultPermission(client); - if (!hasPermission) { - for (String associatedDevice : client.associatedDevices) { - if (associatedDevice.equalsIgnoreCase(address)) { - hasPermission = true; - break; - } - } - } - if (!hasPermission && client.eligibleForSanitizedExposureNotification) { - ScanResult sanitized = getSanitizedExposureNotification(result); - if (sanitized != null) { - hasPermission = true; - result = sanitized; - } - } - boolean matchResult = matchesFilters(client, result, originalAddress); - if (!hasPermission || !matchResult) { - Log.v( - TAG, - "Skipping client: permission=" + hasPermission + " matches=" + matchResult); - continue; - } - - int callbackType = settings.getCallbackType(); - if (!(callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES - || callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH)) { - Log.v(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); - continue; - } - - try { - app.mAppScanStats.addResult(client.scannerId); - if (app.mCallback != null) { - app.mCallback.onScanResult(result); - } else { - Log.v(TAG, "Callback is null, sending scan results by pendingIntent"); - // Send the PendingIntent - ArrayList<ScanResult> results = new ArrayList<>(); - results.add(result); - sendResultsByPendingIntent( - app.mInfo, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); - } - } catch (RemoteException | PendingIntent.CanceledException e) { - Log.e(TAG, "Exception: " + e); - handleDeadScanClient(client); - } - } - } - - private void sendResultByPendingIntent( - PendingIntentInfo pii, ScanResult result, int callbackType, ScanClient client) { - ArrayList<ScanResult> results = new ArrayList<>(); - results.add(result); - try { - sendResultsByPendingIntent(pii, results, callbackType); - } catch (PendingIntent.CanceledException e) { - final long token = Binder.clearCallingIdentity(); - try { - stopScanInternal(client.scannerId); - unregisterScannerInternal(client.scannerId); - } finally { - Binder.restoreCallingIdentity(token); - } - } - } - - @SuppressWarnings("NonApiType") - private void sendResultsByPendingIntent( - PendingIntentInfo pii, ArrayList<ScanResult> results, int callbackType) - throws PendingIntent.CanceledException { - Intent extrasIntent = new Intent(); - extrasIntent.putParcelableArrayListExtra( - BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, results); - extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); - pii.intent.send(mAdapterService, 0, extrasIntent); - } - - private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) - throws PendingIntent.CanceledException { - Intent extrasIntent = new Intent(); - extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); - pii.intent.send(mAdapterService, 0, extrasIntent); - } - - /** Callback method for scanner registration. */ - public void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) - throws RemoteException { - UUID uuid = new UUID(uuidMsb, uuidLsb); - Log.d( - TAG, - "onScannerRegistered() - UUID=" - + uuid - + ", scannerId=" - + scannerId - + ", status=" - + status); - - // First check the callback map - ScannerMap.ScannerApp cbApp = mScannerMap.getByUuid(uuid); - if (cbApp != null) { - if (status == 0) { - cbApp.mId = scannerId; - // If app is callback based, setup a death recipient. App will initiate the start. - // Otherwise, if PendingIntent based, start the scan directly. - if (cbApp.mCallback != null) { - cbApp.linkToDeath(new ScannerDeathRecipient(scannerId, cbApp.mName)); - } else { - continuePiStartScan(scannerId, cbApp); - } - } else { - mScannerMap.remove(scannerId); - } - if (cbApp.mCallback != null) { - cbApp.mCallback.onScannerRegistered(status, scannerId); - } - } - } - - /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ - private boolean hasScanResultPermission(final ScanClient client) { - if (client.hasNetworkSettingsPermission - || client.hasNetworkSetupWizardPermission - || client.hasScanWithoutLocationPermission) { - return true; - } - if (client.hasDisavowedLocation) { - return true; - } - return client.hasLocationPermission - && !Utils.blockedByLocationOff(mAdapterService, client.userHandle); - } - - // Check if a scan record matches a specific filters. - private boolean matchesFilters(ScanClient client, ScanResult scanResult) { - return matchesFilters(client, scanResult, null); - } - - // Check if a scan record matches a specific filters or original address - private boolean matchesFilters( - ScanClient client, ScanResult scanResult, String originalAddress) { - if (client.filters == null || client.filters.isEmpty()) { - // TODO: Do we really wanna return true here? - return true; - } - for (ScanFilter filter : client.filters) { - // Need to check the filter matches, and the original address without changing the API - if (filter.matches(scanResult)) { - return true; - } - if (originalAddress != null - && originalAddress.equalsIgnoreCase(filter.getDeviceAddress())) { - return true; - } - } - return false; - } - - private void handleDeadScanClient(ScanClient client) { - if (client.appDied) { - Log.w(TAG, "Already dead client " + client.scannerId); - return; - } - client.appDied = true; - if (client.stats != null) { - client.stats.isAppDead = true; - } - stopScanInternal(client.scannerId); - } - - /** Callback method for scan filter enablement/disablement. */ - public void onScanFilterEnableDisabled(int action, int status, int clientIf) { - Log.d( - TAG, - "onScanFilterEnableDisabled() - clientIf=" - + clientIf - + ", status=" - + status - + ", action=" - + action); - mScanManager.callbackDone(clientIf, status); - } - - /** Callback method for configuration of scan filter params. */ - public void onScanFilterParamsConfigured( - int action, int status, int clientIf, int availableSpace) { - Log.d( - TAG, - "onScanFilterParamsConfigured() - clientIf=" - + clientIf - + ", status=" - + status - + ", action=" - + action - + ", availableSpace=" - + availableSpace); - mScanManager.callbackDone(clientIf, status); - } - - /** Callback method for configuration of scan filter. */ - public void onScanFilterConfig( - int action, int status, int clientIf, int filterType, int availableSpace) { - Log.d( - TAG, - "onScanFilterConfig() - clientIf=" - + clientIf - + ", action = " - + action - + " status = " - + status - + ", filterType=" - + filterType - + ", availableSpace=" - + availableSpace); - - mScanManager.callbackDone(clientIf, status); - } - - /** Callback method for configuration of batch scan storage. */ - public void onBatchScanStorageConfigured(int status, int clientIf) { - Log.d(TAG, "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); - mScanManager.callbackDone(clientIf, status); - } - - /** Callback method for start/stop of batch scan. */ - // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. - public void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { - Log.d( - TAG, - "onBatchScanStartStopped() - clientIf=" - + clientIf - + ", status=" - + status - + ", startStopAction=" - + startStopAction); - mScanManager.callbackDone(clientIf, status); - } - - ScanClient findBatchScanClientById(int scannerId) { - for (ScanClient client : mScanManager.getBatchScanQueue()) { - if (client.scannerId == scannerId) { - return client; - } - } - return null; - } - - /** Callback method for batch scan reports */ - public void onBatchScanReports( - int status, int scannerId, int reportType, int numRecords, byte[] recordData) - throws RemoteException { - // When in testing mode, ignore all real-world events - if (mTestModeAccessor.isTestModeEnabled()) return; - - AppScanStats.recordBatchScanRadioResultCount(numRecords); - onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); - } - - @VisibleForTesting - void onBatchScanReportsInternal( - int status, int scannerId, int reportType, int numRecords, byte[] recordData) - throws RemoteException { - Log.d( - TAG, - "onBatchScanReports() - scannerId=" - + scannerId - + ", status=" - + status - + ", reportType=" - + reportType - + ", numRecords=" - + numRecords); - - Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); - if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { - // We only support single client for truncated mode. - ScannerMap.ScannerApp app = mScannerMap.getById(scannerId); - if (app == null) { - return; - } - - ScanClient client = findBatchScanClientById(scannerId); - if (client == null) { - return; - } - - ArrayList<ScanResult> permittedResults; - if (hasScanResultPermission(client)) { - permittedResults = new ArrayList<ScanResult>(results); - } else { - permittedResults = new ArrayList<ScanResult>(); - for (ScanResult scanResult : results) { - for (String associatedDevice : client.associatedDevices) { - if (associatedDevice.equalsIgnoreCase( - scanResult.getDevice().getAddress())) { - permittedResults.add(scanResult); - } - } - } - if (permittedResults.isEmpty()) { - return; - } - } - - if (client.hasDisavowedLocation) { - permittedResults.removeIf(mLocationDenylistPredicate); - } - - if (app.mCallback != null) { - app.mCallback.onBatchScanResults(permittedResults); - } else { - // PendingIntent based - try { - sendResultsByPendingIntent( - app.mInfo, permittedResults, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); - } catch (PendingIntent.CanceledException e) { - Log.d(TAG, "Exception while sending result", e); - } - } - } else { - for (ScanClient client : mScanManager.getFullBatchScanQueue()) { - // Deliver results for each client. - deliverBatchScan(client, results); - } - } - mScanManager.callbackDone(scannerId, status); - } - - @SuppressWarnings("NonApiType") - private void sendBatchScanResults( - ScannerMap.ScannerApp app, ScanClient client, ArrayList<ScanResult> results) { - try { - if (app.mCallback != null) { - if (mScanManager.isAutoBatchScanClientEnabled(client)) { - Log.d(TAG, "sendBatchScanResults() to onScanResult()" + client); - for (ScanResult result : results) { - app.mAppScanStats.addResult(client.scannerId); - app.mCallback.onScanResult(result); - } - } else { - Log.d(TAG, "sendBatchScanResults() to onBatchScanResults()" + client); - app.mCallback.onBatchScanResults(results); - } - } else { - sendResultsByPendingIntent( - app.mInfo, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); - } - } catch (RemoteException | PendingIntent.CanceledException e) { - Log.e(TAG, "Exception: " + e); - handleDeadScanClient(client); - } - } - - // Check and deliver scan results for different scan clients. - private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) - throws RemoteException { - ScannerMap.ScannerApp app = mScannerMap.getById(client.scannerId); - if (app == null) { - return; - } - - ArrayList<ScanResult> permittedResults; - if (hasScanResultPermission(client)) { - permittedResults = new ArrayList<ScanResult>(allResults); - } else { - permittedResults = new ArrayList<ScanResult>(); - for (ScanResult scanResult : allResults) { - for (String associatedDevice : client.associatedDevices) { - if (associatedDevice.equalsIgnoreCase(scanResult.getDevice().getAddress())) { - permittedResults.add(scanResult); - } - } - } - if (permittedResults.isEmpty()) { - return; - } - } - - if (client.filters == null || client.filters.isEmpty()) { - sendBatchScanResults(app, client, permittedResults); - // TODO: Question to reviewer: Shouldn't there be a return here? - } - // Reconstruct the scan results. - ArrayList<ScanResult> results = new ArrayList<ScanResult>(); - for (ScanResult scanResult : permittedResults) { - if (matchesFilters(client, scanResult)) { - results.add(scanResult); - } - } - sendBatchScanResults(app, client, results); - } - - private Set<ScanResult> parseBatchScanResults( - int numRecords, int reportType, byte[] batchRecord) { - if (numRecords == 0) { - return Collections.emptySet(); - } - Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); - if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { - return parseTruncatedResults(numRecords, batchRecord); - } else { - return parseFullResults(numRecords, batchRecord); - } - } - - private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { - Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); - Set<ScanResult> results = new HashSet<ScanResult>(numRecords); - long now = SystemClock.elapsedRealtimeNanos(); - for (int i = 0; i < numRecords; ++i) { - byte[] record = - extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); - byte[] address = extractBytes(record, 0, 6); - reverse(address); - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); - int rssi = record[8]; - long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); - results.add( - new ScanResult( - device, ScanRecord.parseFromBytes(new byte[0]), rssi, timestampNanos)); - } - return results; - } - - @VisibleForTesting - long parseTimestampNanos(byte[] data) { - long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); - // Timestamp is in every 50 ms. - return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); - } - - private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { - Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); - Set<ScanResult> results = new HashSet<ScanResult>(numRecords); - int position = 0; - long now = SystemClock.elapsedRealtimeNanos(); - while (position < batchRecord.length) { - byte[] address = extractBytes(batchRecord, position, 6); - // TODO: remove temp hack. - reverse(address); - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); - position += 6; - // Skip address type. - position++; - // Skip tx power level. - position++; - int rssi = batchRecord[position++]; - long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); - position += 2; - - // Combine advertise packet and scan response packet. - int advertisePacketLen = batchRecord[position++]; - byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); - position += advertisePacketLen; - int scanResponsePacketLen = batchRecord[position++]; - byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); - position += scanResponsePacketLen; - byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; - System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); - System.arraycopy( - scanResponseBytes, 0, scanRecord, advertisePacketLen, scanResponsePacketLen); - Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); - results.add( - new ScanResult( - device, ScanRecord.parseFromBytes(scanRecord), rssi, timestampNanos)); - } - return results; - } - - // Reverse byte array. - private void reverse(byte[] address) { - int len = address.length; - for (int i = 0; i < len / 2; ++i) { - byte b = address[i]; - address[i] = address[len - 1 - i]; - address[len - 1 - i] = b; - } - } - - // Helper method to extract bytes from byte array. - private static byte[] extractBytes(byte[] scanRecord, int start, int length) { - byte[] bytes = new byte[length]; - System.arraycopy(scanRecord, start, bytes, 0, length); - return bytes; - } - - public void onBatchScanThresholdCrossed(int clientIf) { - Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); - flushPendingBatchResultsInternal(clientIf); - } - - public AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject( - int clientIf, - int advPktLen, - byte[] advPkt, - int scanRspLen, - byte[] scanRsp, - int filtIndex, - int advState, - int advInfoPresent, - String address, - int addrType, - int txPower, - int rssiValue, - int timeStamp) { - - return new AdvtFilterOnFoundOnLostInfo( - clientIf, - advPktLen, - advPkt, - scanRspLen, - scanRsp, - filtIndex, - advState, - advInfoPresent, - address, - addrType, - txPower, - rssiValue, - timeStamp); - } - - public void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) - throws RemoteException { - Log.d( - TAG, - "onTrackAdvFoundLost() - scannerId= " - + trackingInfo.getClientIf() - + " address = " - + trackingInfo.getAddress() - + " addressType = " - + trackingInfo.getAddressType() - + " adv_state = " - + trackingInfo.getAdvState()); - - ScannerMap.ScannerApp app = mScannerMap.getById(trackingInfo.getClientIf()); - if (app == null) { - Log.e(TAG, "app is null"); - return; - } - - BluetoothDevice device = - BluetoothAdapter.getDefaultAdapter() - .getRemoteLeDevice( - trackingInfo.getAddress(), trackingInfo.getAddressType()); - int advertiserState = trackingInfo.getAdvState(); - ScanResult result = - new ScanResult( - device, - ScanRecord.parseFromBytes(trackingInfo.getResult()), - trackingInfo.getRSSIValue(), - SystemClock.elapsedRealtimeNanos()); - - for (ScanClient client : mScanManager.getRegularScanQueue()) { - if (client.scannerId == trackingInfo.getClientIf()) { - ScanSettings settings = client.settings; - if ((advertiserState == ADVT_STATE_ONFOUND) - && ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) - != 0)) { - if (app.mCallback != null) { - app.mCallback.onFoundOrLost(true, result); - } else { - sendResultByPendingIntent( - app.mInfo, result, ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); - } - } else if ((advertiserState == ADVT_STATE_ONLOST) - && ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST) - != 0)) { - if (app.mCallback != null) { - app.mCallback.onFoundOrLost(false, result); - } else { - sendResultByPendingIntent( - app.mInfo, result, ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); - } - } else { - Log.d( - TAG, - "Not reporting onlost/onfound : " - + advertiserState - + " scannerId = " - + client.scannerId - + " callbackType " - + settings.getCallbackType()); - } - } - } - } - - /** Callback method for configuration of scan parameters. */ - public void onScanParamSetupCompleted(int status, int scannerId) { - Log.d(TAG, "onScanParamSetupCompleted() - scannerId=" + scannerId + ", status=" + status); - ScannerMap.ScannerApp app = mScannerMap.getById(scannerId); - if (app == null || app.mCallback == null) { - Log.e(TAG, "Advertise app or callback is null"); - return; - } - } - - // callback from ScanManager for dispatch of errors apps. - public void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { - ScannerMap.ScannerApp app = mScannerMap.getById(scannerId); - if (app == null) { - Log.e(TAG, "App null"); - return; - } - if (app.mCallback != null) { - app.mCallback.onScanManagerErrorCallback(errorCode); - } else { - try { - sendErrorByPendingIntent(app.mInfo, errorCode); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Error sending error code via PendingIntent:" + e); - } - } - } - - public int msftMonitorHandleFromFilterIndex(int filter_index) { - if (!mFilterIndexToMsftAdvMonitorMap.containsKey(filter_index)) { - Log.e(TAG, "Monitor with filter_index'" + filter_index + "' does not exist"); - return -1; - } - return mFilterIndexToMsftAdvMonitorMap.get(filter_index); - } - - public void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) { - if (status != 0) { - Log.e( - TAG, - "Error adding advertisement monitor with filter index '" + filter_index + "'"); - return; - } - if (mFilterIndexToMsftAdvMonitorMap.containsKey(filter_index)) { - Log.e(TAG, "Monitor with filter_index'" + filter_index + "' already added"); - return; - } - mFilterIndexToMsftAdvMonitorMap.put(filter_index, monitor_handle); - } - - public void onMsftAdvMonitorRemove(int filter_index, int status) { - if (status != 0) { - Log.e( - TAG, - "Error removing advertisement monitor with filter index '" - + filter_index - + "'"); - } - if (!mFilterIndexToMsftAdvMonitorMap.containsKey(filter_index)) { - Log.e(TAG, "Monitor with filter_index'" + filter_index + "' does not exist"); - return; - } - mFilterIndexToMsftAdvMonitorMap.remove(filter_index); - } - - public void onMsftAdvMonitorEnable(int status) { - if (status != 0) { - Log.e(TAG, "Error enabling advertisement monitor"); - } - } - - /************************************************************************** - * GATT Service functions - Shared CLIENT/SERVER - *************************************************************************/ - - @RequiresPermission(BLUETOOTH_SCAN) - public void registerScanner( - IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper registerScanner")) { - return; - } - - enforceImpersonatationPermissionIfNeeded(workSource); - - AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid()); - if (app != null - && app.isScanningTooFrequently() - && !Utils.checkCallerHasPrivilegedPermission(mAdapterService)) { - Log.e(TAG, "App '" + app.mAppName + "' is scanning too frequently"); - try { - callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); - } catch (RemoteException e) { - Log.e(TAG, "Exception: " + e); - } - return; - } - registerScannerInternal(callback, attributionSource, workSource); - } - - /** Intended for internal use within the Bluetooth app. Bypass permission check */ - public void registerScannerInternal( - IScannerCallback callback, AttributionSource attrSource, WorkSource workSource) { - UUID uuid = UUID.randomUUID(); - Log.d(TAG, "registerScanner() - UUID=" + uuid); - - mScannerMap.add(uuid, attrSource, workSource, callback, mAdapterService, this); - mScanManager.registerScanner(uuid); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void unregisterScanner(int scannerId, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper unregisterScanner")) { - return; - } - - unregisterScannerInternal(scannerId); - } - - /** Intended for internal use within the Bluetooth app. Bypass permission check */ - public void unregisterScannerInternal(int scannerId) { - Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); - mScannerMap.remove(scannerId); - mScanManager.unregisterScanner(scannerId); - } - - private List<String> getAssociatedDevices(String callingPackage) { - if (mCompanionManager == null) { - return Collections.emptyList(); - } - - final long identity = Binder.clearCallingIdentity(); - try { - return mCompanionManager.getAllAssociations().stream() - .filter( - info -> - info.getPackageName().equals(callingPackage) - && !info.isSelfManaged() - && info.getDeviceMacAddress() != null) - .map(AssociationInfo::getDeviceMacAddress) - .map(MacAddress::toString) - .collect(Collectors.toList()); - } catch (SecurityException se) { - // Not an app with associated devices - } catch (Exception e) { - Log.e(TAG, "Cannot check device associations for " + callingPackage, e); - } finally { - Binder.restoreCallingIdentity(identity); - } - return Collections.emptyList(); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void startScan( - int scannerId, - ScanSettings settings, - List<ScanFilter> filters, - AttributionSource attributionSource) { - Log.d(TAG, "start scan with filters"); - - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "Starting GATT scan.")) { - return; - } - - enforcePrivilegedPermissionIfNeeded(settings); - String callingPackage = attributionSource.getPackageName(); - settings = enforceReportDelayFloor(settings); - enforcePrivilegedPermissionIfNeeded(filters); - final ScanClient scanClient = new ScanClient(scannerId, settings, filters); - scanClient.userHandle = Binder.getCallingUserHandle(); - mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - scanClient.eligibleForSanitizedExposureNotification = - callingPackage.equals(mExposureNotificationPackage); - - scanClient.hasDisavowedLocation = - Utils.hasDisavowedLocationForScan( - mAdapterService, attributionSource, mTestModeAccessor.isTestModeEnabled()); - - scanClient.isQApp = - checkCallerTargetSdk(mAdapterService, callingPackage, Build.VERSION_CODES.Q); - if (!scanClient.hasDisavowedLocation) { - if (scanClient.isQApp) { - scanClient.hasLocationPermission = - Utils.checkCallerHasFineLocation( - mAdapterService, attributionSource, scanClient.userHandle); - } else { - scanClient.hasLocationPermission = - Utils.checkCallerHasCoarseOrFineLocation( - mAdapterService, attributionSource, scanClient.userHandle); - } - } - scanClient.hasNetworkSettingsPermission = - Utils.checkCallerHasNetworkSettingsPermission(mAdapterService); - scanClient.hasNetworkSetupWizardPermission = - Utils.checkCallerHasNetworkSetupWizardPermission(mAdapterService); - scanClient.hasScanWithoutLocationPermission = - Utils.checkCallerHasScanWithoutLocationPermission(mAdapterService); - scanClient.associatedDevices = getAssociatedDevices(callingPackage); - - startScan(scannerId, settings, filters, scanClient); - } - - /** Intended for internal use within the Bluetooth app. Bypass permission check */ - public void startScanInternal(int scannerId, ScanSettings settings, List<ScanFilter> filters) { - final ScanClient scanClient = new ScanClient(scannerId, settings, filters); - scanClient.userHandle = Binder.getCallingUserHandle(); - scanClient.eligibleForSanitizedExposureNotification = false; - scanClient.hasDisavowedLocation = false; - scanClient.isQApp = true; - scanClient.hasNetworkSettingsPermission = - Utils.checkCallerHasNetworkSettingsPermission(mAdapterService); - scanClient.hasNetworkSetupWizardPermission = - Utils.checkCallerHasNetworkSetupWizardPermission(mAdapterService); - scanClient.hasScanWithoutLocationPermission = - Utils.checkCallerHasScanWithoutLocationPermission(mAdapterService); - scanClient.associatedDevices = Collections.emptyList(); - - startScan(scannerId, settings, filters, scanClient); - } - - private void startScan( - int scannerId, ScanSettings settings, List<ScanFilter> filters, ScanClient scanClient) { - AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); - if (app != null) { - scanClient.stats = app; - boolean isFilteredScan = (filters != null) && !filters.isEmpty(); - boolean isCallbackScan = false; - - ScannerMap.ScannerApp cbApp = mScannerMap.getById(scannerId); - if (cbApp != null) { - isCallbackScan = cbApp.mCallback != null; - } - app.recordScanStart( - settings, - filters, - isFilteredScan, - isCallbackScan, - scannerId, - cbApp == null ? null : cbApp.mAttributionTag); - } - - mScanManager.startScan(scanClient); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void registerPiAndStartScan( - PendingIntent pendingIntent, - ScanSettings settings, - List<ScanFilter> filters, - AttributionSource attributionSource) { - Log.d(TAG, "start scan with filters, for PendingIntent"); - - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "Starting GATT scan.")) { - return; - } - enforcePrivilegedPermissionIfNeeded(settings); - settings = enforceReportDelayFloor(settings); - enforcePrivilegedPermissionIfNeeded(filters); - UUID uuid = UUID.randomUUID(); - String callingPackage = attributionSource.getPackageName(); - int callingUid = attributionSource.getUid(); - PendingIntentInfo piInfo = new PendingIntentInfo(); - piInfo.intent = pendingIntent; - piInfo.settings = settings; - piInfo.filters = filters; - piInfo.callingPackage = callingPackage; - piInfo.callingUid = callingUid; - Log.d( - TAG, - "startScan(PI) -" - + (" UUID=" + uuid) - + (" Package=" + callingPackage) - + (" UID=" + callingUid)); - - // Don't start scan if the Pi scan already in mScannerMap. - if (mScannerMap.getByPendingIntentInfo(piInfo) != null) { - Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap."); - return; - } - - ScannerMap.ScannerApp app = - mScannerMap.add(uuid, attributionSource, piInfo, mAdapterService, this); - - app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); - mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - app.mEligibleForSanitizedExposureNotification = - callingPackage.equals(mExposureNotificationPackage); - - app.mHasDisavowedLocation = - Utils.hasDisavowedLocationForScan( - mAdapterService, attributionSource, mTestModeAccessor.isTestModeEnabled()); - - if (!app.mHasDisavowedLocation) { - try { - if (checkCallerTargetSdk(mAdapterService, callingPackage, Build.VERSION_CODES.Q)) { - app.mHasLocationPermission = - Utils.checkCallerHasFineLocation( - mAdapterService, attributionSource, app.mUserHandle); - } else { - app.mHasLocationPermission = - Utils.checkCallerHasCoarseOrFineLocation( - mAdapterService, attributionSource, app.mUserHandle); - } - } catch (SecurityException se) { - // No need to throw here. Just mark as not granted. - app.mHasLocationPermission = false; - } - } - app.mHasNetworkSettingsPermission = - Utils.checkCallerHasNetworkSettingsPermission(mAdapterService); - app.mHasNetworkSetupWizardPermission = - Utils.checkCallerHasNetworkSetupWizardPermission(mAdapterService); - app.mHasScanWithoutLocationPermission = - Utils.checkCallerHasScanWithoutLocationPermission(mAdapterService); - app.mAssociatedDevices = getAssociatedDevices(callingPackage); - mScanManager.registerScanner(uuid); - - // If this fails, we should stop the scan immediately. - if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) { - Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan."); - stopScan(pendingIntent, attributionSource); - } - } - - /** Start a scan with pending intent. */ - public void continuePiStartScan(int scannerId, ScannerMap.ScannerApp app) { - final PendingIntentInfo piInfo = app.mInfo; - final ScanClient scanClient = - new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.callingUid); - scanClient.hasLocationPermission = app.mHasLocationPermission; - scanClient.userHandle = app.mUserHandle; - scanClient.isQApp = checkCallerTargetSdk(mAdapterService, app.mName, Build.VERSION_CODES.Q); - scanClient.eligibleForSanitizedExposureNotification = - app.mEligibleForSanitizedExposureNotification; - scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission; - scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission; - scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission; - scanClient.associatedDevices = app.mAssociatedDevices; - scanClient.hasDisavowedLocation = app.mHasDisavowedLocation; - - AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId); - if (scanStats != null) { - scanClient.stats = scanStats; - boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); - scanStats.recordScanStart( - piInfo.settings, - piInfo.filters, - isFilteredScan, - false, - scannerId, - app.mAttributionTag); - } - - mScanManager.startScan(scanClient); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper flushPendingBatchResults")) { - return; - } - flushPendingBatchResultsInternal(scannerId); - } - - private void flushPendingBatchResultsInternal(int scannerId) { - Log.d(TAG, "flushPendingBatchResultsInternal - scannerId=" + scannerId); - mScanManager.flushBatchScanResults(new ScanClient(scannerId)); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void stopScan(int scannerId, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper stopScan")) { - return; - } - stopScanInternal(scannerId); - } - - /** Intended for internal use within the Bluetooth app. Bypass permission check */ - public void stopScanInternal(int scannerId) { - int scanQueueSize = - mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size(); - Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); - - AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); - if (app != null) { - app.recordScanStop(scannerId); - } - - mScanManager.stopScan(scannerId); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void stopScan(PendingIntent intent, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper stopScan")) { - return; - } - stopScanInternal(intent); - } - - /** Intended for internal use within the Bluetooth app. Bypass permission check */ - private void stopScanInternal(PendingIntent intent) { - PendingIntentInfo pii = new PendingIntentInfo(); - pii.intent = intent; - ScannerMap.ScannerApp app = mScannerMap.getByPendingIntentInfo(pii); - Log.v(TAG, "stopScan(PendingIntent): app found = " + app); - if (app != null) { - intent.removeCancelListener(mScanIntentCancelListener); - final int scannerId = app.mId; - stopScanInternal(scannerId); - // Also unregister the scanner - unregisterScannerInternal(scannerId); - } - } - - /************************************************************************** - * PERIODIC SCANNING - *************************************************************************/ - @RequiresPermission(BLUETOOTH_SCAN) - public void registerSync( - ScanResult scanResult, - int skip, - int timeout, - IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper registerSync")) { - return; - } - mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void unregisterSync( - IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper unregisterSync")) { - return; - } - mPeriodicScanManager.stopSync(callback); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void transferSync( - BluetoothDevice bda, - int serviceData, - int syncHandle, - AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper transferSync")) { - return; - } - mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public void transferSetInfo( - BluetoothDevice bda, - int serviceData, - int advHandle, - IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper transferSetInfo")) { - return; - } - mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); - } - - @RequiresPermission(BLUETOOTH_SCAN) - public int numHwTrackFiltersAvailable(AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper numHwTrackFiltersAvailable")) { - return 0; - } - return (mAdapterService.getTotalNumOfTrackableAdvertisements() - - getCurrentUsedTrackingAdvertisement()); - } - - /** - * DeathRecipient handler used to unregister applications that disconnect ungracefully (ie. - * crash or forced close). - */ - class ScannerDeathRecipient implements IBinder.DeathRecipient { - int mScannerId; - private String mPackageName; - - ScannerDeathRecipient(int scannerId, String packageName) { - mScannerId = scannerId; - mPackageName = packageName; - } - - @Override - public void binderDied() { - Log.d( - TAG, - "Binder is dead - unregistering scanner (" - + mPackageName - + " " - + mScannerId - + ")!"); - - ScanClient client = getScanClient(mScannerId); - if (client != null) { - handleDeadScanClient(client); - } - } - - private ScanClient getScanClient(int clientIf) { - for (ScanClient client : mScanManager.getRegularScanQueue()) { - if (client.scannerId == clientIf) { - return client; - } - } - for (ScanClient client : mScanManager.getBatchScanQueue()) { - if (client.scannerId == clientIf) { - return client; - } - } - return null; - } - } - - private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { - // BLE scan only mode needs special permission. - if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) { - return true; - } - - // Regular scan, no special permission. - if (settings == null) { - return false; - } - - // Ambient discovery mode, needs privileged permission. - if (settings.getScanMode() == ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY) { - return true; - } - - // Regular scan, no special permission. - if (settings.getReportDelayMillis() == 0) { - return false; - } - - // Batch scan, truncated mode needs permission. - return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; - } - - /* - * The {@link ScanFilter#setDeviceAddress} API overloads are @SystemApi access methods. This - * requires that the permissions be BLUETOOTH_PRIVILEGED. - */ - @SuppressLint("AndroidFrameworkRequiresPermission") - private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) { - Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")"); - // Some 3p API cases may have null filters, need to allow - if (filters != null) { - for (ScanFilter filter : filters) { - // The only case to enforce here is if there is an address - // If there is an address, enforce if the correct combination criteria is met. - if (filter.getDeviceAddress() != null) { - // At this point we have an address, that means a caller used the - // setDeviceAddress(address) public API for the ScanFilter - // We don't want to enforce if the type is PUBLIC and the IRK is null - // However, if we have a different type that means the caller used a new - // @SystemApi such as setDeviceAddress(address, type) or - // setDeviceAddress(address, type, irk) which are both @SystemApi and require - // permissions to be enforced - if (filter.getAddressType() == BluetoothDevice.ADDRESS_TYPE_PUBLIC - && filter.getIrk() == null) { - // Do not enforce - } else { - mAdapterService.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - } - } - } - } - } - - @SuppressLint("AndroidFrameworkRequiresPermission") - private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { - if (needsPrivilegedPermissionForScan(settings)) { - mAdapterService.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - } - } - - // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other - // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does - // not have UPDATE_DEVICE_STATS permission. - @RequiresPermission(UPDATE_DEVICE_STATS) - private void enforceImpersonatationPermission() { - mAdapterService.enforceCallingOrSelfPermission( - UPDATE_DEVICE_STATS, "Need UPDATE_DEVICE_STATS permission"); - } - - @SuppressLint("AndroidFrameworkRequiresPermission") - private void enforceImpersonatationPermissionIfNeeded(WorkSource workSource) { - if (workSource != null) { - enforceImpersonatationPermission(); - } - } - - /** - * Ensures the report delay is either 0 or at least the floor value (5000ms) - * - * @param settings are the scan settings passed into a request to start le scanning - * @return the passed in ScanSettings object if the report delay is 0 or above the floor value; - * a new ScanSettings object with the report delay being the floor value if the original - * report delay was between 0 and the floor value (exclusive of both) - */ - @VisibleForTesting - ScanSettings enforceReportDelayFloor(ScanSettings settings) { - if (settings.getReportDelayMillis() == 0) { - return settings; - } - - // Need to clear identity to pass device config permission check - final long callerToken = Binder.clearCallingIdentity(); - try { - long floor = - DeviceConfig.getLong( - DeviceConfig.NAMESPACE_BLUETOOTH, - "report_delay", - DEFAULT_REPORT_DELAY_FLOOR); - - if (settings.getReportDelayMillis() > floor) { - return settings; - } else { - return new ScanSettings.Builder() - .setCallbackType(settings.getCallbackType()) - .setLegacy(settings.getLegacy()) - .setMatchMode(settings.getMatchMode()) - .setNumOfMatches(settings.getNumOfMatches()) - .setPhy(settings.getPhy()) - .setReportDelay(floor) - .setScanMode(settings.getScanMode()) - .setScanResultType(settings.getScanResultType()) - .build(); - } - } finally { - Binder.restoreCallingIdentity(callerToken); - } - } - - public void addScanEvent(BluetoothMetricsProto.ScanEvent event) { - synchronized (mScanEvents) { - if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { - mScanEvents.remove(); - } - mScanEvents.add(event); - } - } - - public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { - synchronized (mScanEvents) { - builder.addAllScanEvent(mScanEvents); - } - } -} diff --git a/android/app/src/com/android/bluetooth/mapclient/MapClientService.java b/android/app/src/com/android/bluetooth/mapclient/MapClientService.java index 9f282cd233..40aae4bfc1 100644 --- a/android/app/src/com/android/bluetooth/mapclient/MapClientService.java +++ b/android/app/src/com/android/bluetooth/mapclient/MapClientService.java @@ -172,8 +172,11 @@ public class MapClientService extends ProfileService { // When creating a new statemachine, its state is set to CONNECTING - which will trigger // connect. MceStateMachine mapStateMachine; - if (mSmLooper != null) mapStateMachine = new MceStateMachine(this, device, mSmLooper); - else mapStateMachine = new MceStateMachine(this, device); + if (mSmLooper != null) { + mapStateMachine = new MceStateMachine(this, device, mAdapterService, mSmLooper); + } else { + mapStateMachine = new MceStateMachine(this, device, mAdapterService); + } mMapInstanceMap.put(device, mapStateMachine); } diff --git a/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java b/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java index 87c750dfcd..2c3420af84 100644 --- a/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java +++ b/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java @@ -14,24 +14,36 @@ * limitations under the License. */ -/** - * Bluetooth MAP MCE StateMachine (Disconnected) | ^ CONNECT | | DISCONNECTED V | (Connecting) - * (Disconnecting) | ^ CONNECTED | | DISCONNECT V | (Connected) - * - * <p>Valid Transitions: State + Event -> Transition: - * - * <p>Disconnected + CONNECT -> Connecting Connecting + CONNECTED -> Connected Connecting + TIMEOUT - * -> Disconnecting Connecting + DISCONNECT/CONNECT -> Defer Message Connected + DISCONNECT -> - * Disconnecting Connected + CONNECT -> Disconnecting + Defer Message Disconnecting + DISCONNECTED - * -> (Safe) Disconnected Disconnecting + TIMEOUT -> (Force) Disconnected Disconnecting + - * DISCONNECT/CONNECT : Defer Message - */ +// Bluetooth MAP MCE StateMachine +// (Disconnected) +// | ^ +// CONNECT | | DISCONNECTED +// V | +// (Connecting) (Disconnecting) +// | ^ +// CONNECTED | | DISCONNECT +// V | +// (Connected) + +// Valid Transitions: State + Event -> Transition: + +// Disconnected + CONNECT -> Connecting +// Connecting + CONNECTED -> Connected +// Connecting + TIMEOUT -> Disconnecting +// Connecting + DISCONNECT/CONNECT -> Defer Message +// Connected + DISCONNECT -> Disconnecting +// Connected + CONNECT -> Disconnecting + Defer Message +// Disconnecting + DISCONNECTED -> (Safe) Disconnected +// Disconnecting + TIMEOUT -> (Force) Disconnected +// Disconnecting + DISCONNECT/CONNECT : Defer Message package com.android.bluetooth.mapclient; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.RECEIVE_SMS; +import static java.util.Objects.requireNonNull; + import android.app.Activity; import android.app.PendingIntent; import android.bluetooth.BluetoothDevice; @@ -64,6 +76,7 @@ import com.android.vcard.VCardConstants; import com.android.vcard.VCardEntry; import com.android.vcard.VCardProperty; +import java.time.Duration; import java.time.Instant; import java.util.Calendar; import java.util.HashMap; @@ -100,12 +113,12 @@ class MceStateMachine extends StateMachine { // Bluetooth, to work with the default Car Messenger. This may need to be set to false if the // messaging app takes that responsibility. private static final Boolean SAVE_OUTBOUND_MESSAGES = true; - private static final int DISCONNECT_TIMEOUT = 3000; - private static final int CONNECT_TIMEOUT = 10000; + @VisibleForTesting static final Duration DISCONNECT_TIMEOUT = Duration.ofSeconds(3); + @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(10); private static final int MAX_MESSAGES = 20; private static final int MSG_CONNECT = 1; private static final int MSG_DISCONNECT = 2; - static final int MSG_CONNECTING_TIMEOUT = 3; + private static final int MSG_CONNECTING_TIMEOUT = 3; private static final int MSG_DISCONNECTING_TIMEOUT = 4; // Constants for SDP. Note that these values come from the native stack, but no centralized @@ -136,22 +149,26 @@ class MceStateMachine extends StateMachine { private static final String SEND_MESSAGE_TYPE = "persist.bluetooth.pts.mapclient.sendmessagetype"; + private final State mDisconnected = new Disconnected(); + private final State mConnecting = new Connecting(); + private final State mConnected = new Connected(); + private final State mDisconnecting = new Disconnecting(); + + private final HashMap<String, Bmessage> mSentMessageLog = new HashMap<>(MAX_MESSAGES); + private final HashMap<Bmessage, PendingIntent> mSentReceiptRequested = + new HashMap<>(MAX_MESSAGES); + private final HashMap<Bmessage, PendingIntent> mDeliveryReceiptRequested = + new HashMap<>(MAX_MESSAGES); + + private final BluetoothDevice mDevice; + private final MapClientService mService; + private final AdapterService mAdapterService; + // Connectivity States private int mPreviousState = BluetoothProfile.STATE_DISCONNECTED; private int mMostRecentState = BluetoothProfile.STATE_DISCONNECTED; - private State mDisconnected; - private State mConnecting; - private State mConnected; - private State mDisconnecting; - - private final BluetoothDevice mDevice; - private MapClientService mService; private MasClient mMasClient; private MapClientContent mDatabase; - private HashMap<String, Bmessage> mSentMessageLog = new HashMap<>(MAX_MESSAGES); - private HashMap<Bmessage, PendingIntent> mSentReceiptRequested = new HashMap<>(MAX_MESSAGES); - private HashMap<Bmessage, PendingIntent> mDeliveryReceiptRequested = - new HashMap<>(MAX_MESSAGES); private final Object mLock = new Object(); @@ -214,36 +231,33 @@ class MceStateMachine extends StateMachine { ConcurrentHashMap<String, MessageMetadata> mMessages = new ConcurrentHashMap<String, MessageMetadata>(); - MceStateMachine(MapClientService service, BluetoothDevice device) { - this(service, device, null, null); - } - - MceStateMachine(MapClientService service, BluetoothDevice device, Looper looper) { - this(service, device, null, null, looper); + MceStateMachine( + MapClientService service, BluetoothDevice device, AdapterService adapterService) { + super(TAG); // Create a state machine with its own separate thread + mAdapterService = requireNonNull(adapterService); + mService = service; + mDevice = device; + initStateMachine(); } - @VisibleForTesting MceStateMachine( MapClientService service, BluetoothDevice device, - MasClient masClient, - MapClientContent database) { - super(TAG); - mService = service; - mMasClient = masClient; - mDevice = device; - mDatabase = database; - initStateMachine(); + AdapterService adapterService, + Looper looper) { + this(service, device, adapterService, looper, null, null); } @VisibleForTesting MceStateMachine( MapClientService service, BluetoothDevice device, + AdapterService adapterService, + Looper looper, MasClient masClient, - MapClientContent database, - Looper looper) { - super(TAG, looper); + MapClientContent database) { + super(TAG, requireNonNull(looper)); + mAdapterService = requireNonNull(adapterService); mService = service; mMasClient = masClient; mDevice = device; @@ -254,10 +268,6 @@ class MceStateMachine extends StateMachine { private void initStateMachine() { mPreviousState = BluetoothProfile.STATE_DISCONNECTED; - mDisconnected = new Disconnected(); - mConnecting = new Connecting(); - mDisconnecting = new Disconnecting(); - mConnected = new Connected(); addState(mDisconnected); addState(mConnecting); @@ -302,11 +312,8 @@ class MceStateMachine extends StateMachine { } setState(state); - AdapterService adapterService = AdapterService.getAdapterService(); - if (adapterService != null) { - adapterService.updateProfileConnectionAdapterProperties( - mDevice, BluetoothProfile.MAP_CLIENT, state, prevState); - } + mAdapterService.updateProfileConnectionAdapterProperties( + mDevice, BluetoothProfile.MAP_CLIENT, state, prevState); Intent intent = new Intent(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); @@ -552,7 +559,7 @@ class MceStateMachine extends StateMachine { // When commanded to connect begin SDP to find the MAS server. mDevice.sdpSearch(BluetoothUuid.MAS); - sendMessageDelayed(MSG_CONNECTING_TIMEOUT, CONNECT_TIMEOUT); + sendMessageDelayed(MSG_CONNECTING_TIMEOUT, CONNECT_TIMEOUT.toMillis()); Log.i(TAG, Utils.getLoggableAddress(mDevice) + " [Connecting]: Await SDP results"); } @@ -1270,7 +1277,7 @@ class MceStateMachine extends StateMachine { if (mMasClient != null) { mMasClient.makeRequest(new RequestSetNotificationRegistration(false)); mMasClient.shutdown(); - sendMessageDelayed(MSG_DISCONNECTING_TIMEOUT, DISCONNECT_TIMEOUT); + sendMessageDelayed(MSG_DISCONNECTING_TIMEOUT, DISCONNECT_TIMEOUT.toMillis()); } else { // MAP was never connected transitionTo(mDisconnected); @@ -1345,10 +1352,6 @@ class MceStateMachine extends StateMachine { return "MSG_GET_MESSAGE_LISTING"; case MSG_SET_MESSAGE_STATUS: return "MSG_SET_MESSAGE_STATUS"; - case DISCONNECT_TIMEOUT: - return "DISCONNECT_TIMEOUT"; - case CONNECT_TIMEOUT: - return "CONNECT_TIMEOUT"; case MSG_CONNECT: return "MSG_CONNECT"; case MSG_DISCONNECT: diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java index 6efdb17d66..7bf72bcee1 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java @@ -51,7 +51,6 @@ import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.Utils; -import com.android.bluetooth.flags.Flags; import com.google.common.annotations.VisibleForTesting; @@ -234,7 +233,7 @@ class BluetoothOppNotification { case NOTIFY: synchronized (BluetoothOppNotification.this) { if (mPendingUpdate > 0 && mUpdateNotificationThread == null) { - Log.v(TAG, "new notify threadi!"); + Log.v(TAG, "new notify thread!"); mUpdateNotificationThread = new NotificationUpdateThread(); mUpdateNotificationThread.start(); Log.v(TAG, "send delay message"); diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java index a8c653db5c..4bf981a0a5 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppService.java @@ -51,7 +51,6 @@ import android.database.Cursor; import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.net.Uri; -import android.os.Binder; import android.os.Handler; import android.os.Message; import android.os.Process; @@ -135,7 +134,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti private BluetoothShareContentObserver mObserver; /** Class to handle Notification Manager updates */ - @VisibleForTesting BluetoothOppNotification mNotifier; + @VisibleForTesting final BluetoothOppNotification mNotifier; private boolean mPendingUpdate; @@ -236,28 +235,6 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__LOG_WARN, 0); } - } - - public static boolean isEnabled() { - return BluetoothProperties.isProfileOppEnabled().orElse(false); - } - - @Override - protected IProfileServiceBinder initBinder() { - return new OppBinder(); - } - - private static class OppBinder extends Binder implements IProfileServiceBinder { - - OppBinder() {} - - @Override - public void cleanup() {} - } - - @Override - public void start() { - Log.v(TAG, "start()"); setComponentAvailable(OPP_PROVIDER, true); setComponentAvailable(INCOMING_FILE_CONFIRM_ACTIVITY, true); @@ -282,6 +259,15 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti setBluetoothOppService(this); } + public static boolean isEnabled() { + return BluetoothProperties.isProfileOppEnabled().orElse(false); + } + + @Override + protected IProfileServiceBinder initBinder() { + return null; + } + @Override public void stop() { if (sBluetoothOppService == null) { @@ -457,7 +443,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti BluetoothStatsLog .BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION, 7); - Log.e(TAG, "close tranport error"); + Log.e(TAG, "close transport error"); } } else { Log.i(TAG, "OPP busy! Retry after 1 second"); @@ -623,9 +609,7 @@ public class BluetoothOppService extends ProfileService implements IObexConnecti } } - if (mNotifier != null) { - mNotifier.cancelOppNotifications(); - } + mNotifier.cancelOppNotifications(); } /* suppose we auto accept an incoming OPUSH connection */ diff --git a/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java b/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java index 0580c58560..cb4f561b73 100644 --- a/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java @@ -22,41 +22,19 @@ import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.util.Log; -import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; /** Provides Bluetooth Pan native interface for the Pan service */ public class PanNativeInterface { private static final String TAG = PanNativeInterface.class.getSimpleName(); - private PanService mPanService; - @GuardedBy("INSTANCE_LOCK") - private static PanNativeInterface sInstance; + private final PanService mPanService; - private static final Object INSTANCE_LOCK = new Object(); - - private PanNativeInterface() {} - - /** Get singleton instance. */ - public static PanNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new PanNativeInterface(); - } - return sInstance; - } - } - - /** Set singleton instance. */ - @VisibleForTesting - public static void setInstance(PanNativeInterface instance) { - synchronized (INSTANCE_LOCK) { - sInstance = instance; - } + PanNativeInterface(PanService panService) { + mPanService = panService; } - void init(PanService panService) { - mPanService = panService; + void init() { initializeNative(); } diff --git a/android/app/src/com/android/bluetooth/pan/PanService.java b/android/app/src/com/android/bluetooth/pan/PanService.java index ee57196ac4..d59d74e0c5 100644 --- a/android/app/src/com/android/bluetooth/pan/PanService.java +++ b/android/app/src/com/android/bluetooth/pan/PanService.java @@ -19,6 +19,10 @@ package com.android.bluetooth.pan; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.TETHER_PRIVILEGED; +import static android.bluetooth.BluetoothUtils.logRemoteException; + +import static java.util.Objects.requireNonNull; +import static java.util.Objects.requireNonNullElseGet; import android.annotation.RequiresPermission; import android.bluetooth.BluetoothDevice; @@ -29,7 +33,6 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetoothPan; import android.bluetooth.IBluetoothPanCallback; import android.content.AttributionSource; -import android.content.Context; import android.content.Intent; import android.content.res.Resources.NotFoundException; import android.net.TetheringInterface; @@ -57,53 +60,49 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; /** Provides Bluetooth Pan Device profile, as a service in the Bluetooth application. */ public class PanService extends ProfileService { private static final String TAG = PanService.class.getSimpleName(); + private static PanService sPanService; private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5; - @VisibleForTesting ConcurrentHashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices; - - private int mMaxPanDevices; - private String mPanIfName; - @VisibleForTesting boolean mIsTethering = false; - private HashMap<String, IBluetoothPanCallback> mBluetoothTetheringCallbacks; - - private TetheringManager mTetheringManager; - private DatabaseManager mDatabaseManager; - @VisibleForTesting UserManager mUserManager; - private static final int MESSAGE_CONNECT = 1; private static final int MESSAGE_DISCONNECT = 2; private static final int MESSAGE_CONNECT_STATE_CHANGED = 11; - private boolean mTetherOn = false; - private BluetoothTetheringNetworkFactory mNetworkFactory; - private boolean mStarted = false; + @VisibleForTesting + final ConcurrentHashMap<BluetoothDevice, BluetoothPanDevice> mPanDevices = + new ConcurrentHashMap<>(); - private AdapterService mAdapterService; + private final Map<String, IBluetoothPanCallback> mBluetoothTetheringCallbacks = new HashMap<>(); + private final AdapterService mAdapterService; + private final PanNativeInterface mNativeInterface; + private final DatabaseManager mDatabaseManager; + private final TetheringManager mTetheringManager; + private final UserManager mUserManager; + private final int mMaxPanDevices; - @VisibleForTesting PanNativeInterface mNativeInterface; + private String mPanIfName; + @VisibleForTesting boolean mIsTethering = false; + private boolean mTetherOn = false; + private BluetoothTetheringNetworkFactory mNetworkFactory; - TetheringManager.TetheringEventCallback mTetheringCallback = + final TetheringManager.TetheringEventCallback mTetheringCallback = new TetheringManager.TetheringEventCallback() { @Override public void onError(TetheringInterface iface, int error) { if (mIsTethering && iface.getType() == TetheringManager.TETHERING_BLUETOOTH) { - // tethering is fail because of @TetheringIfaceError error. + // Tethering fail because of @TetheringIfaceError error. Log.e(TAG, "Error setting up tether interface: " + error); - for (Map.Entry device : mPanDevices.entrySet()) { + for (BluetoothDevice device : mPanDevices.keySet()) { mNativeInterface.disconnect( Flags.panUseIdentityAddress() - ? Utils.getByteBrEdrAddress( - (BluetoothDevice) device.getKey()) - : Utils.getByteAddress( - (BluetoothDevice) device.getKey())); + ? Utils.getByteBrEdrAddress(mAdapterService, device) + : Utils.getByteAddress(device)); } mPanDevices.clear(); mIsTethering = false; @@ -111,8 +110,35 @@ public class PanService extends ProfileService { } }; - public PanService(Context ctx) { - super(ctx); + public PanService(AdapterService adapterService) { + this(adapterService, null); + } + + @VisibleForTesting + PanService(AdapterService adapterService, PanNativeInterface nativeInterface) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; + mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); + mNativeInterface = + requireNonNullElseGet(nativeInterface, () -> new PanNativeInterface(this)); + mUserManager = requireNonNull(getSystemService(UserManager.class)); + mTetheringManager = requireNonNull(getSystemService(TetheringManager.class)); + + int maxPanDevice; + try { + maxPanDevice = + getResources() + .getInteger(com.android.bluetooth.R.integer.config_max_pan_devices); + } catch (NotFoundException e) { + maxPanDevice = BLUETOOTH_MAX_PAN_CONNECTIONS; + } + mMaxPanDevices = maxPanDevice; + + mNativeInterface.init(); + + mTetheringManager.registerTetheringEventCallback( + new HandlerExecutor(new Handler(Looper.getMainLooper())), mTetheringCallback); + setPanService(this); } public static boolean isEnabled() { @@ -143,50 +169,8 @@ public class PanService extends ProfileService { } @Override - public void start() { - mAdapterService = - Objects.requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null when PanService starts"); - mDatabaseManager = - Objects.requireNonNull( - AdapterService.getAdapterService().getDatabase(), - "DatabaseManager cannot be null when PanService starts"); - mNativeInterface = - Objects.requireNonNull( - PanNativeInterface.getInstance(), - "PanNativeInterface cannot be null when PanService starts"); - - mBluetoothTetheringCallbacks = new HashMap<>(); - mPanDevices = new ConcurrentHashMap<BluetoothDevice, BluetoothPanDevice>(); - try { - mMaxPanDevices = - getResources() - .getInteger(com.android.bluetooth.R.integer.config_max_pan_devices); - } catch (NotFoundException e) { - mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS; - } - mNativeInterface.init(this); - - mUserManager = getSystemService(UserManager.class); - - mTetheringManager = getSystemService(TetheringManager.class); - mTetheringManager.registerTetheringEventCallback( - new HandlerExecutor(new Handler(Looper.getMainLooper())), mTetheringCallback); - setPanService(this); - mStarted = true; - } - - @Override public void stop() { - if (!mStarted) { - Log.w(TAG, "stop() called before start()"); - return; - } - if (mTetheringManager != null) { - mTetheringManager.unregisterTetheringEventCallback(mTetheringCallback); - mTetheringManager = null; - } + mTetheringManager.unregisterTetheringEventCallback(mTetheringCallback); mNativeInterface.cleanup(); mHandler.removeCallbacksAndMessages(null); } @@ -196,29 +180,25 @@ public class PanService extends ProfileService { // TODO(b/72948646): this should be moved to stop() setPanService(null); - mUserManager = null; - - if (mPanDevices != null) { - int[] desiredStates = { - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_DISCONNECTING - }; - List<BluetoothDevice> devList = getDevicesMatchingConnectionStates(desiredStates); - for (BluetoothDevice device : devList) { - BluetoothPanDevice panDevice = mPanDevices.get(device); - Log.d(TAG, "panDevice: " + panDevice + " device address: " + device); - if (panDevice != null) { - handlePanDeviceStateChange( - device, - mPanIfName, - BluetoothProfile.STATE_DISCONNECTED, - panDevice.mLocalRole, - panDevice.mRemoteRole); - } + int[] desiredStates = { + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_CONNECTED, + BluetoothProfile.STATE_DISCONNECTING + }; + List<BluetoothDevice> devList = getDevicesMatchingConnectionStates(desiredStates); + for (BluetoothDevice device : devList) { + BluetoothPanDevice panDevice = mPanDevices.get(device); + Log.d(TAG, "panDevice: " + panDevice + " device address: " + device); + if (panDevice != null) { + handlePanDeviceStateChange( + device, + mPanIfName, + BluetoothProfile.STATE_DISCONNECTED, + panDevice.mLocalRole, + panDevice.mRemoteRole); } - mPanDevices.clear(); } + mPanDevices.clear(); } private final Handler mHandler = @@ -230,7 +210,8 @@ public class PanService extends ProfileService { BluetoothDevice connectDevice = (BluetoothDevice) msg.obj; if (!mNativeInterface.connect( Flags.identityAddressNullIfNotKnown() - ? Utils.getByteBrEdrAddress(connectDevice) + ? Utils.getByteBrEdrAddress( + mAdapterService, connectDevice) : mAdapterService.getByteIdentityAddress( connectDevice))) { handlePanDeviceStateChange( @@ -251,7 +232,8 @@ public class PanService extends ProfileService { BluetoothDevice disconnectDevice = (BluetoothDevice) msg.obj; if (!mNativeInterface.disconnect( Flags.identityAddressNullIfNotKnown() - ? Utils.getByteBrEdrAddress(disconnectDevice) + ? Utils.getByteBrEdrAddress( + mAdapterService, disconnectDevice) : mAdapterService.getByteIdentityAddress( disconnectDevice))) { handlePanDeviceStateChange( @@ -663,7 +645,7 @@ public class PanService extends ProfileService { mPanDevices.remove(device); mNativeInterface.disconnect( Flags.panUseIdentityAddress() - ? Utils.getByteBrEdrAddress(device) + ? Utils.getByteBrEdrAddress(mAdapterService, device) : Utils.getByteAddress(device)); return; } @@ -675,7 +657,7 @@ public class PanService extends ProfileService { cb.onAvailable(iface); } } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + logRemoteException(TAG, e); } } } else if (state == BluetoothProfile.STATE_DISCONNECTED) { @@ -690,12 +672,12 @@ public class PanService extends ProfileService { cb.onUnavailable(); } } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + logRemoteException(TAG, e); } mIsTethering = false; } } - } else if (mStarted) { + } else { // PANU Role = reverse Tether Log.d( TAG, diff --git a/android/app/src/com/android/bluetooth/sap/SapService.java b/android/app/src/com/android/bluetooth/sap/SapService.java index 6401b27f82..861553477b 100644 --- a/android/app/src/com/android/bluetooth/sap/SapService.java +++ b/android/app/src/com/android/bluetooth/sap/SapService.java @@ -19,6 +19,8 @@ package com.android.bluetooth.sap; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static java.util.Objects.requireNonNull; + import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.app.AlarmManager; @@ -60,15 +62,10 @@ import java.util.Collections; import java.util.List; public class SapService extends ProfileService implements AdapterService.BluetoothStateCallback { + private static final String TAG = "SapService"; private static final String SDP_SAP_SERVICE_NAME = "SIM Access"; private static final int SDP_SAP_VERSION = 0x0102; - private static final String TAG = "SapService"; - - /** - * To log debug/verbose in SAP, use the command "setprop log.tag.SapService DEBUG" or "setprop - * log.tag.SapService VERBOSE" and then "adb root" + "adb shell "stop; start"" - */ /* Message ID's */ private static final int START_LISTENER = 1; @@ -100,8 +97,9 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo "com.android.bluetooth.sap.USER_CONFIRM_TIMEOUT"; private static final int USER_CONFIRM_TIMEOUT_VALUE = 25000; + private final AdapterService mAdapterService; + private PowerManager.WakeLock mWakeLock = null; - private AdapterService mAdapterService; private SocketAcceptThread mAcceptThread = null; private BluetoothServerSocket mServerSocket = null; private int mSdpHandle = -1; @@ -113,9 +111,7 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo private SapServer mSapServer = null; private AlarmManager mAlarmManager = null; private boolean mRemoveTimeoutMsg = false; - private boolean mIsWaitingAuthorization = false; - private boolean mIsRegistered = false; private static SapService sSapService; @@ -123,9 +119,22 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo BluetoothUuid.SAP, }; - public SapService(Context ctx) { - super(ctx); + public SapService(AdapterService adapterService) { + super(requireNonNull(adapterService)); + mAdapterService = adapterService; BluetoothSap.invalidateBluetoothGetConnectionStateCache(); + + IntentFilter filter = new IntentFilter(); + filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); + filter.addAction(USER_CONFIRM_TIMEOUT_ACTION); + + registerReceiver(mSapReceiver, filter); + + mAdapterService.registerBluetoothStateCallback(getMainExecutor(), this); + // start RFCOMM listener + mSessionStatusHandler.sendMessage(mSessionStatusHandler.obtainMessage(START_LISTENER)); + setSapService(this); } public static boolean isEnabled() { @@ -148,7 +157,7 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo private void removeSdpRecord() { SdpManagerNativeInterface nativeInterface = SdpManagerNativeInterface.getInstance(); - if (mAdapterService != null && mSdpHandle >= 0 && nativeInterface.isAvailable()) { + if (mSdpHandle >= 0 && nativeInterface.isAvailable()) { Log.v(TAG, "Removing SDP record handle: " + mSdpHandle); nativeInterface.removeSdpRecord(mSdpHandle); mSdpHandle = -1; @@ -203,9 +212,6 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo if (!initSocketOK) { // Need to break out of this loop if BT is being turned off. - if (mAdapterService == null) { - break; - } int state = mAdapterService.getState(); if ((state != BluetoothAdapter.STATE_TURNING_ON) && (state != BluetoothAdapter.STATE_ON)) { @@ -636,7 +642,7 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo Log.d(TAG, "Saved connectionPolicy " + device + " = " + connectionPolicy); enforceCallingOrSelfPermission( BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); - AdapterService.getAdapterService() + mAdapterService .getDatabase() .setProfileConnectionPolicy(device, BluetoothProfile.SAP, connectionPolicy); if (connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { @@ -659,7 +665,7 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo public int getConnectionPolicy(BluetoothDevice device) { enforceCallingOrSelfPermission( BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); - return AdapterService.getAdapterService() + return mAdapterService .getDatabase() .getProfileConnectionPolicy(device, BluetoothProfile.SAP); } @@ -670,41 +676,10 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo } @Override - public void start() { - Log.v(TAG, "start()"); - IntentFilter filter = new IntentFilter(); - filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); - filter.addAction(USER_CONFIRM_TIMEOUT_ACTION); - - try { - registerReceiver(mSapReceiver, filter); - mIsRegistered = true; - } catch (Exception e) { - Log.w(TAG, "Unable to register sap receiver", e); - } - mInterrupted = false; - mAdapterService = AdapterService.getAdapterService(); - mAdapterService.registerBluetoothStateCallback(getMainExecutor(), this); - // start RFCOMM listener - mSessionStatusHandler.sendMessage(mSessionStatusHandler.obtainMessage(START_LISTENER)); - setSapService(this); - } - - @Override public void stop() { Log.v(TAG, "stop()"); - if (!mIsRegistered) { - Log.i(TAG, "Avoid unregister when receiver it is not registered"); - return; - } setSapService(null); - try { - mIsRegistered = false; - unregisterReceiver(mSapReceiver); - } catch (Exception e) { - Log.w(TAG, "Unable to unregister sap receiver", e); - } + unregisterReceiver(mSapReceiver); mAdapterService.unregisterBluetoothStateCallback(this); setState(BluetoothSap.STATE_DISCONNECTED, BluetoothSap.RESULT_CANCELED); sendShutdownMessage(); diff --git a/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java b/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java index 2fa94bd27e..eacdefbb06 100644 --- a/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java +++ b/android/app/src/com/android/bluetooth/telephony/BluetoothInCallService.java @@ -148,8 +148,6 @@ public class BluetoothInCallService extends InCallService { private final CallInfo mCallInfo; - protected boolean mOnCreateCalled = false; - private int mMaxNumberOfCalls = 0; private BluetoothAdapter mAdapter = null; @@ -367,7 +365,6 @@ public class BluetoothInCallService extends InCallService { private BluetoothInCallService(CallInfo callInfo) { Log.i(TAG, "BluetoothInCallService is created"); mCallInfo = Objects.requireNonNullElseGet(callInfo, () -> new CallInfo()); - sInstance = this; mExecutor = Executors.newSingleThreadExecutor(); } @@ -546,10 +543,6 @@ public class BluetoothInCallService extends InCallService { @RequiresPermission(allOf = {BLUETOOTH_CONNECT, MODIFY_PHONE_STATE}) public boolean listCurrentCalls() { synchronized (LOCK) { - if (!mOnCreateCalled) { - Log.w(TAG, "listcurrentCalls() is called before onCreate()"); - return false; - } enforceModifyPermission(); // only log if it is after we recently updated the headset state or else it can // clog the android log since this can be queried every second. @@ -780,25 +773,28 @@ public class BluetoothInCallService extends InCallService { @Override public void onCreate() { - Log.d(TAG, "onCreate"); super.onCreate(); - mAdapter = requireNonNull(getSystemService(BluetoothManager.class)).getAdapter(); - mTelephonyManager = requireNonNull(getSystemService(TelephonyManager.class)); - mTelecomManager = requireNonNull(getSystemService(TelecomManager.class)); - mAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.HEADSET); - mAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.LE_CALL_CONTROL); - mBluetoothAdapterReceiver = new BluetoothAdapterReceiver(); - IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); - intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - registerReceiver(mBluetoothAdapterReceiver, intentFilter); - mOnCreateCalled = true; + synchronized (LOCK) { + Log.d(TAG, "onCreate"); + mAdapter = requireNonNull(getSystemService(BluetoothManager.class)).getAdapter(); + mTelephonyManager = requireNonNull(getSystemService(TelephonyManager.class)); + mTelecomManager = requireNonNull(getSystemService(TelecomManager.class)); + mAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.HEADSET); + mAdapter.getProfileProxy(this, mProfileListener, BluetoothProfile.LE_CALL_CONTROL); + mBluetoothAdapterReceiver = new BluetoothAdapterReceiver(); + IntentFilter intentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); + intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); + registerReceiver(mBluetoothAdapterReceiver, intentFilter); + sInstance = this; + } } @Override public void onDestroy() { - Log.d(TAG, "onDestroy"); - clear(); - mOnCreateCalled = false; + synchronized (LOCK) { + Log.d(TAG, "onDestroy"); + clear(); + } super.onDestroy(); } diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java index e0868e416a..1b22f9c136 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java @@ -31,6 +31,9 @@ import static android.bluetooth.IBluetoothCsipSetCoordinator.CSIS_GROUP_ID_INVAL import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; import static android.bluetooth.IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME; +import static com.android.bluetooth.flags.Flags.leaudioBroadcastVolumeControlPrimaryGroupOnly; +import static com.android.bluetooth.flags.Flags.vcpDeviceVolumeApiImprovements; + import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElseGet; @@ -64,7 +67,6 @@ import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.csip.CsipSetCoordinatorService; -import com.android.bluetooth.flags.Flags; import com.android.bluetooth.le_audio.LeAudioService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -117,9 +119,12 @@ public class VolumeControlService extends ProfileService { new HashMap<>(); private final Map<BluetoothDevice, VolumeControlInputDescriptor> mAudioInputs = new ConcurrentHashMap<>(); - private final Map<Integer, Integer> mGroupVolumeCache = new HashMap<>(); - private final Map<Integer, Boolean> mGroupMuteCache = new HashMap<>(); - private final Map<BluetoothDevice, Integer> mDeviceVolumeCache = new HashMap<>(); + private final Map<Integer, Integer> mGroupVolumeCache = new ConcurrentHashMap<>(); + private final Map<Integer, Boolean> mGroupMuteCache = new ConcurrentHashMap<>(); + private final Map<BluetoothDevice, Integer> mDeviceVolumeCache = new ConcurrentHashMap<>(); + private final Map<BluetoothDevice, Boolean> mDeviceMuteCache = new ConcurrentHashMap<>(); + + private Boolean mIgnoreSetVolumeFromAF = false; @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); @@ -198,6 +203,7 @@ public class VolumeControlService extends ProfileService { mGroupVolumeCache.clear(); mGroupMuteCache.clear(); mDeviceVolumeCache.clear(); + mDeviceMuteCache.clear(); synchronized (mCallbacks) { mCallbacks.kill(); @@ -529,7 +535,8 @@ public class VolumeControlService extends ProfileService { mNativeInterface.setExtAudioOutVolumeOffset(device, instanceId, volumeOffset); } - void setDeviceVolume(BluetoothDevice device, int volume, boolean isGroupOp) { + public synchronized void setDeviceVolume( + BluetoothDevice device, int volume, boolean isGroupOp) { Log.d( TAG, "setDeviceVolume: " + device + ", volume: " + volume + ", isGroupOp: " + isGroupOp); @@ -551,18 +558,60 @@ public class VolumeControlService extends ProfileService { Log.i(TAG, "Setting individual device volume"); mDeviceVolumeCache.put(device, volume); mNativeInterface.setVolume(device, volume); + + if (vcpDeviceVolumeApiImprovements()) { + // We only receive the volume change and mute state needs to be acquired manually + Boolean isStreamMute = + mAudioManager.isStreamMute(getBluetoothContextualVolumeStream()); + adjustDeviceMute(device, volume, isStreamMute); + } + } + } + + private void adjustDeviceMute(BluetoothDevice device, int volume, Boolean isStreamMute) { + Boolean isMute = getMute(device); + if (!isMute.equals(isStreamMute)) { + Log.w( + TAG, + "Mute state mismatch, stream mute: " + + isStreamMute + + ", device mute: " + + isMute + + ", new volume: " + + volume); + if (isStreamMute) { + Log.i(TAG, "Mute the device " + device); + mute(device); + } + if (!isStreamMute && (volume > 0)) { + Log.i(TAG, "Unmute the device " + device); + unmute(device); + } } } - public void setGroupVolume(int groupId, int volume) { + public synchronized void setGroupVolume(int groupId, int volume) { Log.d(TAG, "setGroupVolume: " + groupId + ", volume: " + volume); + if (mIgnoreSetVolumeFromAF) { + Log.d(TAG, "setGroupVolume ignored (from AF) because persisted/cached volume was used"); + mIgnoreSetVolumeFromAF = false; + return; + } + if (volume < 0) { Log.w(TAG, "Tried to set invalid volume " + volume + ". Ignored."); return; } - mGroupVolumeCache.put(groupId, volume); + synchronized (mDeviceVolumeCache) { + mGroupVolumeCache.put(groupId, volume); + if (vcpDeviceVolumeApiImprovements()) { + for (BluetoothDevice dev : getGroupDevices(groupId)) { + mDeviceVolumeCache.put(dev, volume); + } + } + } mNativeInterface.setGroupVolume(groupId, volume); // We only receive the volume change and mute state needs to be acquired manually @@ -594,21 +643,60 @@ public class VolumeControlService extends ProfileService { Log.i(TAG, "Unmute the group " + groupId); unmuteGroup(groupId); } + } else if (vcpDeviceVolumeApiImprovements()) { + for (BluetoothDevice device : getGroupDevices(groupId)) { + adjustDeviceMute(device, volume, isStreamMute); + } } } + /** + * Get group cached volume. If not cached, then try to read from any device from this group. + * + * @param groupId the group identifier + * @return the cached volume + */ public int getGroupVolume(int groupId) { - return mGroupVolumeCache.getOrDefault(groupId, VOLUME_CONTROL_UNKNOWN_VOLUME); + if (vcpDeviceVolumeApiImprovements()) { + synchronized (mDeviceVolumeCache) { + Integer volume = mGroupVolumeCache.get(groupId); + if (volume != null) { + return volume; + } + Log.w(TAG, "No group volume available"); + for (BluetoothDevice device : getGroupDevices(groupId)) { + volume = mDeviceVolumeCache.get(device); + if (volume != null) { + Log.w(TAG, "Volume taken from device: " + device); + return volume; + } + } + return VOLUME_CONTROL_UNKNOWN_VOLUME; + } + } else { + return mGroupVolumeCache.getOrDefault(groupId, VOLUME_CONTROL_UNKNOWN_VOLUME); + } } /** - * Get device cached volume. + * Get device cached volume. If not cached, then try to read from its group. * * @param device the device * @return the cached volume */ public int getDeviceVolume(BluetoothDevice device) { - return mDeviceVolumeCache.getOrDefault(device, VOLUME_CONTROL_UNKNOWN_VOLUME); + if (vcpDeviceVolumeApiImprovements()) { + synchronized (mDeviceVolumeCache) { + Integer volume = mDeviceVolumeCache.get(device); + if (volume != null) { + return volume; + } + return mGroupVolumeCache.getOrDefault( + getGroupId(device), VOLUME_CONTROL_UNKNOWN_VOLUME); + } + } else { + return mDeviceVolumeCache.getOrDefault(device, VOLUME_CONTROL_UNKNOWN_VOLUME); + } } /** @@ -617,7 +705,7 @@ public class VolumeControlService extends ProfileService { * @param groupId the group identifier * @param active indicator if group is active or not */ - public void setGroupActive(int groupId, boolean active) { + public synchronized void setGroupActive(int groupId, boolean active) { Log.d(TAG, "setGroupActive: " + groupId + ", active: " + active); if (!active) { /* For now we don't need to handle group inactivation */ @@ -634,27 +722,75 @@ public class VolumeControlService extends ProfileService { } /** + * Get device cached mute status. If not cached, then try to read from its group. + * + * @param device the device + * @return mute status + */ + public Boolean getMute(BluetoothDevice device) { + synchronized (mDeviceMuteCache) { + Boolean isMute = mDeviceMuteCache.get(device); + if (isMute != null) { + return isMute; + } + return mGroupMuteCache.getOrDefault(getGroupId(device), false); + } + } + + /** + * Get group cached mute status. If not cached, then try to read from any device from this + * group. + * * @param groupId the group identifier + * @return mute status */ public Boolean getGroupMute(int groupId) { - return mGroupMuteCache.getOrDefault(groupId, false); + if (vcpDeviceVolumeApiImprovements()) { + synchronized (mDeviceMuteCache) { + Boolean isMute = mGroupMuteCache.get(groupId); + if (isMute != null) { + return isMute; + } + for (BluetoothDevice device : getGroupDevices(groupId)) { + isMute = mDeviceMuteCache.get(device); + if (isMute != null) { + return isMute; + } + } + return false; + } + } else { + return mGroupMuteCache.getOrDefault(groupId, false); + } } public void mute(BluetoothDevice device) { + mDeviceMuteCache.put(device, true); mNativeInterface.mute(device); } public void muteGroup(int groupId) { - mGroupMuteCache.put(groupId, true); + synchronized (mDeviceMuteCache) { + mGroupMuteCache.put(groupId, true); + for (BluetoothDevice dev : getGroupDevices(groupId)) { + mDeviceMuteCache.put(dev, true); + } + } mNativeInterface.muteGroup(groupId); } public void unmute(BluetoothDevice device) { + mDeviceMuteCache.put(device, false); mNativeInterface.unmute(device); } public void unmuteGroup(int groupId) { - mGroupMuteCache.put(groupId, false); + synchronized (mDeviceMuteCache) { + mGroupMuteCache.put(groupId, false); + for (BluetoothDevice dev : getGroupDevices(groupId)) { + mDeviceMuteCache.put(dev, false); + } + } mNativeInterface.unmuteGroup(groupId); } @@ -724,7 +860,7 @@ public class VolumeControlService extends ProfileService { notifyNewCallbackOfKnownVolumeInfo(callback); } - public void handleGroupNodeAdded(int groupId, BluetoothDevice device) { + public synchronized void handleGroupNodeAdded(int groupId, BluetoothDevice device) { // Ignore disconnected device, its volume will be set once it connects synchronized (mStateMachines) { VolumeControlStateMachine sm = mStateMachines.get(device); @@ -737,18 +873,33 @@ public class VolumeControlService extends ProfileService { } // If group volume has already changed, the new group member should set it - Integer groupVolume = getGroupVolume(groupId); - if (groupVolume != VOLUME_CONTROL_UNKNOWN_VOLUME) { - Log.i(TAG, "Setting value:" + groupVolume + " to " + device); - mNativeInterface.setVolume(device, groupVolume); - } - - Boolean isGroupMuted = getGroupMute(groupId); - Log.i(TAG, "Setting mute:" + isGroupMuted + " to " + device); - if (isGroupMuted) { - mNativeInterface.mute(device); + if (vcpDeviceVolumeApiImprovements()) { + int volume = getDeviceVolume(device); + if (volume != VOLUME_CONTROL_UNKNOWN_VOLUME) { + Log.i(TAG, "Setting device/group volume:" + volume + " to the device:" + device); + setDeviceVolume(device, volume, false); + Boolean isDeviceMuted = getMute(device); + Log.i(TAG, "Setting mute:" + isDeviceMuted + " to " + device); + if (isDeviceMuted) { + mute(device); + } else { + unmute(device); + } + } } else { - mNativeInterface.unmute(device); + Integer groupVolume = getGroupVolume(groupId); + if (groupVolume != VOLUME_CONTROL_UNKNOWN_VOLUME) { + Log.i(TAG, "Setting value:" + groupVolume + " to " + device); + mNativeInterface.setVolume(device, groupVolume); + } + + Boolean isGroupMuted = getGroupMute(groupId); + Log.i(TAG, "Setting mute:" + isGroupMuted + " to " + device); + if (isGroupMuted) { + mNativeInterface.mute(device); + } else { + mNativeInterface.unmute(device); + } } } @@ -769,14 +920,22 @@ public class VolumeControlService extends ProfileService { return; } - mGroupVolumeCache.put(groupId, volume); - mGroupMuteCache.put(groupId, mute); + synchronized (mDeviceVolumeCache) { + mGroupVolumeCache.put(groupId, volume); + mGroupMuteCache.put(groupId, mute); + if (vcpDeviceVolumeApiImprovements()) { + for (BluetoothDevice dev : getGroupDevices(groupId)) { + mDeviceVolumeCache.put(dev, volume); + mDeviceMuteCache.put(dev, mute); + } + } + } LeAudioService leAudioService = mFactory.getLeAudioService(); if (leAudioService != null) { int currentlyActiveGroupId = leAudioService.getActiveGroupId(); if (currentlyActiveGroupId == GROUP_ID_INVALID || groupId != currentlyActiveGroupId) { - if (!Flags.leaudioBroadcastVolumeControlPrimaryGroupOnly()) { + if (!leaudioBroadcastVolumeControlPrimaryGroupOnly()) { Log.i( TAG, "Skip updating to audio system if not updating volume for current" @@ -823,7 +982,7 @@ public class VolumeControlService extends ProfileService { return (int) Math.round((double) streamVolume * LE_AUDIO_MAX_VOL / streamMaxVolume); } - void handleVolumeControlChanged( + synchronized void handleVolumeControlChanged( BluetoothDevice device, int groupId, int volume, @@ -838,9 +997,6 @@ public class VolumeControlService extends ProfileService { return; } - int groupVolume = getGroupVolume(groupId); - Boolean groupMute = getGroupMute(groupId); - if (isAutonomous && device != null) { Log.i( TAG, @@ -851,25 +1007,59 @@ public class VolumeControlService extends ProfileService { /* We are here, because system has just started and LeAudio device is connected. If * remote device has User Persistent flag set, Android sets the volume to local cache * and to the audio system if not already streaming to other devices. - * If Reset Flag is set, then Android sets to remote devices either cached volume volume - * taken from audio manager. + * If Reset Flag is set, then Android sets to remote devices either cached volume or + * volume taken from audio manager (AF always call setVolume via LeAudioService at first + * connected remote from group). * Note, to match BR/EDR behavior, don't show volume change in UI here */ if (((flags & VOLUME_FLAGS_PERSISTED_USER_SET_VOLUME_MASK) == 0x01) && (getConnectedDevices(groupId).size() == 1)) { Log.i(TAG, "Setting device: " + device + " volume: " + volume + " to the system"); + if (vcpDeviceVolumeApiImprovements()) { + // Ignore volume from AF because persisted volume was used + mIgnoreSetVolumeFromAF = true; + } updateGroupCacheAndAudioSystem(groupId, volume, mute, false); return; } // Reset flag is used - if (groupVolume != VOLUME_CONTROL_UNKNOWN_VOLUME) { - Log.i(TAG, "Setting group volume: " + groupVolume + " to the device: " + device); - setGroupVolume(groupId, groupVolume); + if (vcpDeviceVolumeApiImprovements()) { + int deviceVolume = getDeviceVolume(device); + if (deviceVolume != VOLUME_CONTROL_UNKNOWN_VOLUME) { + Log.i( + TAG, + "Setting device/group volume: " + + deviceVolume + + " to the device: " + + device); + setDeviceVolume(device, deviceVolume, false); + Boolean isDeviceMuted = getMute(device); + Log.i(TAG, "Setting mute:" + isDeviceMuted + " to " + device); + if (isDeviceMuted) { + mute(device); + } else { + unmute(device); + } + if (getConnectedDevices(groupId).size() == 1) { + // Ignore volume from AF because cached volume was used + mIgnoreSetVolumeFromAF = true; + } + } } else { - int systemVolume = getBleVolumeFromCurrentStream(); - Log.i(TAG, "Setting system volume: " + systemVolume + " to the group: " + groupId); - setGroupVolume(groupId, systemVolume); + int groupVolume = getGroupVolume(groupId); + if (groupVolume != VOLUME_CONTROL_UNKNOWN_VOLUME) { + Log.i( + TAG, + "Setting group volume: " + groupVolume + " to the device: " + device); + setGroupVolume(groupId, groupVolume); + } else { + int systemVolume = getBleVolumeFromCurrentStream(); + Log.i( + TAG, + "Setting system volume: " + systemVolume + " to the group: " + groupId); + setGroupVolume(groupId, systemVolume); + } } return; @@ -894,13 +1084,16 @@ public class VolumeControlService extends ProfileService { } } - if (!isAutonomous) { + if (!vcpDeviceVolumeApiImprovements() && !isAutonomous) { /* If the change is triggered by Android device, the stream is already changed. * However it might be called with isAutonomous, one the first read of after * reconnection. Make sure device has group volume. Also it might happen that * remote side send us wrong value - lets check it. */ + int groupVolume = getGroupVolume(groupId); + Boolean groupMute = getGroupMute(groupId); + if ((groupVolume == volume) && (groupMute == mute)) { Log.i(TAG, " Volume:" + volume + ", mute:" + mute + " confirmed by remote side."); return; @@ -936,7 +1129,9 @@ public class VolumeControlService extends ProfileService { + " expected volume: " + groupVolume); } - } else { + } + + if (isAutonomous && device == null) { /* Received group notification for autonomous change. Update cache and audio system. */ updateGroupCacheAndAudioSystem(groupId, volume, mute, true); } @@ -1249,7 +1444,7 @@ public class VolumeControlService extends ProfileService { input.onGainSettingsPropertiesChanged(id, unit, min, max); } - void handleStackEvent(VolumeControlStackEvent stackEvent) { + synchronized void handleStackEvent(VolumeControlStackEvent stackEvent) { if (!isAvailable()) { Log.e(TAG, "Event ignored, service not available: " + stackEvent); return; @@ -1375,10 +1570,13 @@ public class VolumeControlService extends ProfileService { int broadcastVolume = VOLUME_CONTROL_UNKNOWN_VOLUME; if (volume.isPresent()) { broadcastVolume = volume.get(); - mDeviceVolumeCache.put(dev, broadcastVolume); + if (!vcpDeviceVolumeApiImprovements()) { + mDeviceVolumeCache.put(dev, broadcastVolume); + } } else { broadcastVolume = getDeviceVolume(dev); - if (broadcastVolume == VOLUME_CONTROL_UNKNOWN_VOLUME) { + if (!vcpDeviceVolumeApiImprovements() + && broadcastVolume == VOLUME_CONTROL_UNKNOWN_VOLUME) { broadcastVolume = getGroupVolume(getGroupId(dev)); } } @@ -1474,7 +1672,7 @@ public class VolumeControlService extends ProfileService { Log.d(TAG, device + " is unbond. Remove state machine"); removeStateMachine(device); } - } else if (toState == STATE_CONNECTED) { + } else if (!vcpDeviceVolumeApiImprovements() && toState == STATE_CONNECTED) { // Restore the group volume if it was changed while the device was not yet connected. Integer groupId = getGroupId(device); if (groupId != GROUP_ID_INVALID) { @@ -2025,5 +2223,18 @@ public class VolumeControlService extends ProfileService { + ", mute: " + getGroupMute(entry.getKey())); } + + if (vcpDeviceVolumeApiImprovements()) { + for (Map.Entry<BluetoothDevice, Integer> entry : mDeviceVolumeCache.entrySet()) { + ProfileService.println( + sb, + " Device: " + + entry.getKey() + + " volume: " + + entry.getValue() + + ", mute: " + + getMute(entry.getKey())); + } + } } } diff --git a/android/app/tests/unit/AndroidTest.xml b/android/app/tests/unit/AndroidTest.xml index 212b245d6e..5ac9bd5608 100644 --- a/android/app/tests/unit/AndroidTest.xml +++ b/android/app/tests/unit/AndroidTest.xml @@ -55,6 +55,6 @@ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> <option name="enable" value="true" /> - <option name="mainline-module-package-name" value="com.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> </object> </configuration> diff --git a/android/app/tests/unit/GoogleAndroidTest.xml b/android/app/tests/unit/GoogleAndroidTest.xml index 61a5011c8f..bcda5eacce 100644 --- a/android/app/tests/unit/GoogleAndroidTest.xml +++ b/android/app/tests/unit/GoogleAndroidTest.xml @@ -51,6 +51,6 @@ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> <option name="enable" value="true" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java index 04527233f0..156151e9b0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java @@ -16,6 +16,8 @@ package com.android.bluetooth.a2dp; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; @@ -243,22 +245,22 @@ public class A2dpCodecConfigTest { for (BluetoothCodecConfig config : codecConfigs) { switch (config.getCodecType()) { case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC: - Assert.assertEquals(config.getCodecPriority(), SBC_PRIORITY_DEFAULT); + assertThat(config.getCodecPriority()).isEqualTo(SBC_PRIORITY_DEFAULT); break; case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC: - Assert.assertEquals(config.getCodecPriority(), AAC_PRIORITY_DEFAULT); + assertThat(config.getCodecPriority()).isEqualTo(AAC_PRIORITY_DEFAULT); break; case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX: - Assert.assertEquals(config.getCodecPriority(), APTX_PRIORITY_DEFAULT); + assertThat(config.getCodecPriority()).isEqualTo(APTX_PRIORITY_DEFAULT); break; case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD: - Assert.assertEquals(config.getCodecPriority(), APTX_HD_PRIORITY_DEFAULT); + assertThat(config.getCodecPriority()).isEqualTo(APTX_HD_PRIORITY_DEFAULT); break; case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC: - Assert.assertEquals(config.getCodecPriority(), LDAC_PRIORITY_DEFAULT); + assertThat(config.getCodecPriority()).isEqualTo(LDAC_PRIORITY_DEFAULT); break; case BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS: - Assert.assertEquals(config.getCodecPriority(), OPUS_PRIORITY_DEFAULT); + assertThat(config.getCodecPriority()).isEqualTo(OPUS_PRIORITY_DEFAULT); break; } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java index 4b67658962..cd9ad4dd9a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java @@ -44,7 +44,6 @@ import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -274,7 +273,7 @@ public class BrowserPlayerWrapperTest { MediaBrowser.ConnectionCallback browserConnCb = mBrowserConnCb.getValue(); browserConnCb.onConnected(); - Assert.assertEquals("root_folder", wrapper.getRootId()); + assertThat(wrapper.getRootId()).isEqualTo("root_folder"); verify(mMockBrowser).disconnect(); } @@ -392,22 +391,22 @@ public class BrowserPlayerWrapperTest { for (int i = 0; i < item_list.size(); i++) { MediaItem expected = items.get(i); ListItem item = item_list.get(i); - Assert.assertEquals(expected.isBrowsable(), item.isFolder); + assertThat(item.isFolder).isEqualTo(expected.isBrowsable()); if (item.isFolder) { Folder folder = item.folder; assertThat(folder).isNotNull(); assertThat(folder.isPlayable).isFalse(); - Assert.assertEquals(expected.getDescription().getMediaId(), folder.mediaId); - Assert.assertEquals(expected.getDescription().getTitle().toString(), folder.title); + assertThat(folder.mediaId).isEqualTo(expected.getDescription().getMediaId()); + assertThat(folder.title).isEqualTo(expected.getDescription().getTitle().toString()); } else { Metadata song = item.song; assertThat(song).isNotNull(); - Assert.assertEquals(expected.getDescription().getMediaId(), song.mediaId); - Assert.assertEquals(expected.getDescription().getTitle().toString(), song.title); - Assert.assertEquals( - expected.getDescription().getSubtitle().toString(), song.artist); - Assert.assertEquals( - expected.getDescription().getDescription().toString(), song.album); + assertThat(song.mediaId).isEqualTo(expected.getDescription().getMediaId()); + assertThat(song.title).isEqualTo(expected.getDescription().getTitle().toString()); + assertThat(song.artist) + .isEqualTo(expected.getDescription().getSubtitle().toString()); + assertThat(song.album) + .isEqualTo(expected.getDescription().getDescription().toString()); if (expected.getDescription().getIconBitmap() != null) { assertThat(song.image).isNotNull(); Bitmap expectedBitmap = expected.getDescription().getIconBitmap(); @@ -415,7 +414,7 @@ public class BrowserPlayerWrapperTest { } else if (expected.getDescription().getIconUri() != null) { assertThat(mTestBitmap.sameAs(song.image.getImage())).isTrue(); } else { - Assert.assertEquals(null, song.image); + assertThat(song.image).isNull(); } } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java index c8e6a9f200..c8b03d632f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java @@ -16,6 +16,8 @@ package com.android.bluetooth.audio_util; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.*; import android.content.Context; @@ -31,7 +33,6 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -77,6 +78,10 @@ public class MediaPlayerListTest { when(mMockContext.getSystemServiceName(AudioManager.class)) .thenReturn(Context.AUDIO_SERVICE); + // MediaSessionManager is final and Bluetooth can't use extended Mockito to mock it. Thus, + // using this as is risks leaking device state into the tests. To avoid this, the injected + // controller and player below in the factory pattern will essentially replace each found + // player with the *same* mock, giving us only one player in the end-- "testPlayer" mMediaSessionManager = InstrumentationRegistry.getTargetContext() .getSystemService(MediaSessionManager.class); @@ -86,9 +91,6 @@ public class MediaPlayerListTest { when(mMockContext.getSystemServiceName(MediaSessionManager.class)) .thenReturn(Context.MEDIA_SESSION_SERVICE); - mMediaPlayerList = - new MediaPlayerList(Looper.myLooper(), InstrumentationRegistry.getTargetContext()); - when(mMockContext.registerReceiver(any(), any())).thenReturn(null); when(mMockContext.getApplicationContext()).thenReturn(mMockContext); when(mMockContext.getPackageManager()).thenReturn(mockPackageManager); @@ -96,13 +98,18 @@ public class MediaPlayerListTest { BrowsablePlayerConnector mockConnector = mock(BrowsablePlayerConnector.class); BrowsablePlayerConnector.setInstanceForTesting(mockConnector); - mMediaPlayerList.init(mMediaUpdateCallback); MediaControllerFactory.inject(mMockController); MediaPlayerWrapperFactory.inject(mMockPlayerWrapper); doReturn("testPlayer").when(mMockController).getPackageName(); when(mMockPlayerWrapper.isMetadataSynced()).thenReturn(false); + + // Be sure to do this setup last, after factor injections, or you risk leaking device state + // into the tests + mMediaPlayerList = + new MediaPlayerList(Looper.myLooper(), InstrumentationRegistry.getTargetContext()); + mMediaPlayerList.init(mMediaUpdateCallback); mMediaPlayerList.setActivePlayer(mMediaPlayerList.addMediaPlayer(mMockController)); verify(mMockPlayerWrapper).registerCallback(mPlayerWrapperCb.capture()); @@ -132,7 +139,7 @@ public class MediaPlayerListTest { } @Test - public void testUpdateMeidaDataForAudioPlaybackWhenAcitvePlayNotPlaying() { + public void testUpdateMediaDataForAudioPlaybackWhenActivePlayNotPlaying() { // Verify update media data with playing state doReturn(prepareMediaData(PlaybackState.STATE_PAUSED)) .when(mMockPlayerWrapper) @@ -140,7 +147,7 @@ public class MediaPlayerListTest { mMediaPlayerList.injectAudioPlaybacActive(true); verify(mMediaUpdateCallback).run(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals(data.state.getState(), PlaybackState.STATE_PLAYING); + assertThat(data.state.getState()).isEqualTo(PlaybackState.STATE_PLAYING); // verify update media data with current media player media data MediaData currentMediaData = prepareMediaData(PlaybackState.STATE_PAUSED); @@ -148,9 +155,9 @@ public class MediaPlayerListTest { mMediaPlayerList.injectAudioPlaybacActive(false); verify(mMediaUpdateCallback, times(2)).run(mMediaUpdateData.capture()); data = mMediaUpdateData.getValue(); - Assert.assertEquals(data.metadata, currentMediaData.metadata); - Assert.assertEquals(data.state.toString(), currentMediaData.state.toString()); - Assert.assertEquals(data.queue, currentMediaData.queue); + assertThat(data.metadata).isEqualTo(currentMediaData.metadata); + assertThat(data.state.toString()).isEqualTo(currentMediaData.state.toString()); + assertThat(data.queue).isEqualTo(currentMediaData.queue); } @Test @@ -165,7 +172,7 @@ public class MediaPlayerListTest { } @Test - public void testNotUdpateMediaDataForAudioPlaybackWhenActivePlayerIsPlaying() { + public void testNotUpdateMediaDataForAudioPlaybackWhenActivePlayerIsPlaying() { // Verify not update media data for Audio Playback when active player is playing doReturn(prepareMediaData(PlaybackState.STATE_PLAYING)) .when(mMockPlayerWrapper) @@ -176,7 +183,7 @@ public class MediaPlayerListTest { } @Test - public void testNotUdpateMediaDataForActivePlayerWhenAudioPlaybackIsActive() { + public void testNotUpdateMediaDataForActivePlayerWhenAudioPlaybackIsActive() { doReturn(prepareMediaData(PlaybackState.STATE_PLAYING)) .when(mMockPlayerWrapper) .getCurrentMediaData(); @@ -219,7 +226,7 @@ public class MediaPlayerListTest { MediaPlayerWrapper newActiveMediaPlayer = mMediaPlayerList.getActivePlayer(); // Should be the same as before. - Assert.assertEquals(activeMediaPlayer, newActiveMediaPlayer); + assertThat(activeMediaPlayer).isEqualTo(newActiveMediaPlayer); session.release(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java index 2ffe3589d5..2b323d9810 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java @@ -39,7 +39,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -257,7 +256,7 @@ public class MediaPlayerWrapperTest { verify(mMockController).registerCallback(mControllerCbs.capture(), any()); MediaController.Callback controllerCallbacks = mControllerCbs.getValue(); - // Update Metdata returned by controller + // Update Metadata returned by controller mTestMetadata.putString(MediaMetadata.METADATA_KEY_TITLE, "New Title"); doReturn(mTestMetadata.build()).when(mMockController).getMetadata(); controllerCallbacks.onMetadataChanged(mTestMetadata.build()); @@ -265,15 +264,9 @@ public class MediaPlayerWrapperTest { // Assert that the metadata was updated and playback state wasn't verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); - Assert.assertEquals( - "Returned PlaybackState isn't equal to original PlaybackState", - data.state.toString(), - mTestState.build().toString()); - Assert.assertEquals("Returned Queue isn't empty", data.queue.size(), 0); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); + assertThat(data.queue).isEmpty(); // Update PlaybackState returned by controller mTestState.setActiveQueueItemId(103); @@ -283,15 +276,9 @@ public class MediaPlayerWrapperTest { // Assert that the PlaybackState was changed but metadata stayed the same verify(mTestCbs, times(2)).mediaUpdatedCallback(mMediaUpdateData.capture()); data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned PlaybackState isn't equal to given PlaybackState", - data.state.toString(), - mTestState.build().toString()); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); - Assert.assertEquals("Returned Queue isn't empty", data.queue.size(), 0); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.queue).isEmpty(); // Verify that there are no timeout messages pending and there were no timeouts assertThat(wrapper.getTimeoutHandler().hasMessages(MSG_TIMEOUT)).isFalse(); @@ -332,15 +319,9 @@ public class MediaPlayerWrapperTest { // Assert that both metadata and playback state are there. verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned PlaybackState isn't equal to given PlaybackState", - data.state.toString(), - mTestState.build().toString()); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); - Assert.assertEquals("Returned Queue isn't empty", data.queue.size(), 0); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.queue).isEmpty(); // Verify that there are no timeout messages pending and there were no timeouts assertThat(wrapper.getTimeoutHandler().hasMessages(MSG_TIMEOUT)).isFalse(); @@ -371,10 +352,7 @@ public class MediaPlayerWrapperTest { // Assert that the metadata returned by getMetadata() is used instead of null verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned metadata is incorrect", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); } @Test @@ -402,10 +380,7 @@ public class MediaPlayerWrapperTest { verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned PlaybackState is incorrect", - data.state.toString(), - mTestState.build().toString()); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); } @Test @@ -428,7 +403,7 @@ public class MediaPlayerWrapperTest { // Assert that both metadata and playback state are there. verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals("Returned Queue isn't null", data.queue.size(), 0); + assertThat(data.queue).isEmpty(); } /* @@ -446,9 +421,10 @@ public class MediaPlayerWrapperTest { // Call getCurrentQueue() multiple times. for (int i = 0; i < 3; i++) { - Assert.assertEquals( - Util.toMetadataList(mMockContext, getQueueFromDescriptions(mTestQueue)), - wrapper.getCurrentQueue()); + assertThat(wrapper.getCurrentQueue()) + .isEqualTo( + Util.toMetadataList( + mMockContext, getQueueFromDescriptions(mTestQueue))); } doReturn(mTestMetadata.build()).when(mMockController).getMetadata(); @@ -471,9 +447,8 @@ public class MediaPlayerWrapperTest { assertThat(Util.toMetadata(mMockContext, mTestMetadata.build()).duration) .isNotEqualTo(wrapper.getCurrentQueue().get(0).duration); doReturn(mTestMetadata.build()).when(mMockController).getMetadata(); - Assert.assertEquals( - Util.toMetadata(mMockContext, mTestMetadata.build()).duration, - wrapper.getCurrentQueue().get(0).duration); + assertThat(wrapper.getCurrentQueue().get(0).duration) + .isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build()).duration); // The MediaController Metadata should still not be equal to the queue // as the track count is different and should not be overridden. assertThat(Util.toMetadata(mMockContext, mTestMetadata.build())) @@ -506,15 +481,9 @@ public class MediaPlayerWrapperTest { // Assert that both metadata and only the first playback state is there. verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned PlaybackState isn't equal to given PlaybackState", - data.state.toString(), - mTestState.build().toString()); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); - Assert.assertEquals("Returned Queue isn't empty", data.queue.size(), 0); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.queue).isEmpty(); // Update PlaybackState returned by controller (Shouldn't trigger update) mTestState.setState(PlaybackState.STATE_PLAYING, 1020, 1.0f); @@ -623,18 +592,10 @@ public class MediaPlayerWrapperTest { verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); verify(mFailHandler, never()).onTerribleFailure(any(), any(), anyBoolean()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); - Assert.assertEquals( - "Returned PlaybackState isn't equal to given PlaybackState", - data.state.toString(), - mTestState.build().toString()); - Assert.assertEquals( - "Returned Queue isn't equal to given Queue", - data.queue, - Util.toMetadataList(mMockContext, getQueueFromDescriptions(mTestQueue))); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); + assertThat(data.queue) + .isEqualTo(Util.toMetadataList(mMockContext, getQueueFromDescriptions(mTestQueue))); // Verify that there are no timeout messages pending and there were no timeouts assertThat(wrapper.getTimeoutHandler().hasMessages(MSG_TIMEOUT)).isFalse(); @@ -673,18 +634,10 @@ public class MediaPlayerWrapperTest { // Assert that the callback was called with the mismatch data verify(mTestCbs).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, mTestMetadata.build())); - Assert.assertEquals( - "Returned PlaybackState isn't equal to given PlaybackState", - data.state.toString(), - mTestState.build().toString()); - Assert.assertEquals( - "Returned Queue isn't equal to given Queue", - data.queue, - Util.toMetadataList(mMockContext, getQueueFromDescriptions(mTestQueue))); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, mTestMetadata.build())); + assertThat(data.state.toString()).isEqualTo(mTestState.build().toString()); + assertThat(data.queue) + .isEqualTo(Util.toMetadataList(mMockContext, getQueueFromDescriptions(mTestQueue))); } /* @@ -711,7 +664,7 @@ public class MediaPlayerWrapperTest { s.setState(PlaybackState.STATE_PAUSED, 0, 1.0f); MediaDescription.Builder d = new MediaDescription.Builder(); for (int i = 1; i <= numTestLoops; i++) { - // Setup Media Info for current itteration + // Setup Media Info for current iteration m.putString(MediaMetadata.METADATA_KEY_TITLE, "BT Fuzz Song " + i); m.putString(MediaMetadata.METADATA_KEY_ARTIST, "BT Fuzz Artist " + i); m.putString(MediaMetadata.METADATA_KEY_ALBUM, "BT Fuzz Album " + i); @@ -751,18 +704,9 @@ public class MediaPlayerWrapperTest { // that all the Media info matches what was given verify(mTestCbs, times(i)).mediaUpdatedCallback(mMediaUpdateData.capture()); MediaData data = mMediaUpdateData.getValue(); - Assert.assertEquals( - "Returned Metadata isn't equal to given Metadata", - data.metadata, - Util.toMetadata(mMockContext, m.build())); - Assert.assertEquals( - "Returned PlaybackState isn't equal to given PlaybackState", - data.state.toString(), - s.build().toString()); - Assert.assertEquals( - "Returned Queue isn't equal to given Queue", - data.queue, - Util.toMetadataList(mMockContext, q)); + assertThat(data.metadata).isEqualTo(Util.toMetadata(mMockContext, m.build())); + assertThat(data.state.toString()).isEqualTo(s.build().toString()); + assertThat(data.queue).isEqualTo(Util.toMetadataList(mMockContext, q)); } // Verify that there are no timeout messages pending and there were no timeouts diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java index 03a05875b2..ae189d26e2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java @@ -50,9 +50,7 @@ import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; -import org.hamcrest.core.IsInstanceOf; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -173,7 +171,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToBeIdle(sm.getHandler().getLooper()); // is disconnected - Assert.assertEquals(sm.getState(), BluetoothProfile.STATE_DISCONNECTED); + assertThat(sm.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); // told mAvrcpControllerService to remove it verify(mAvrcpControllerService).removeStateMachine(eq(sm)); @@ -203,19 +201,17 @@ public class AvrcpControllerStateMachineTest { */ private int setUpConnectedState(boolean control, boolean browsing) { - Assert.assertThat( - mAvrcpStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class)); + assertThat(mAvrcpStateMachine.getCurrentState()) + .isInstanceOf(AvrcpControllerStateMachine.Disconnected.class); mAvrcpStateMachine.connect(StackEvent.connectionStateChanged(control, browsing)); TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); verify(mAvrcpControllerService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) .sendBroadcast(mIntentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertThat( - mAvrcpStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Connected.class)); - Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_CONNECTED); + assertThat(mAvrcpStateMachine.getCurrentState()) + .isInstanceOf(AvrcpControllerStateMachine.Connected.class); + assertThat(mAvrcpStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); return BluetoothProfile.STATE_CONNECTED; } @@ -273,7 +269,7 @@ public class AvrcpControllerStateMachineTest { mAvrcpStateMachine.sendMessage( AvrcpControllerStateMachine.MESSAGE_PROCESS_TRACK_CHANGED, track); TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); - Assert.assertEquals(mAvrcpStateMachine.getCurrentTrack(), track); + assertThat(mAvrcpStateMachine.getCurrentTrack()).isEqualTo(track); } /** Set the current play status (Play, Pause, etc.) of the device */ @@ -328,35 +324,7 @@ public class AvrcpControllerStateMachineTest { // Make sure its set by re grabbing the node and checking its contents are cached nowPlaying = mAvrcpStateMachine.findNode("NOW_PLAYING"); assertThat(nowPlaying.isCached()).isTrue(); - assertNowPlayingList(nowPlayingList); - } - - private String avrcpItemListToString(List<AvrcpItem> items) { - StringBuilder s = new StringBuilder(); - s.append("["); - if (items != null) { - for (int i = 0; i < items.size(); i++) { - AvrcpItem item = items.get(i); - s.append((item != null ? Long.toString(item.getUid()) : "null")); - if (i != items.size() - 1) s.append(", "); - } - } - s.append("]"); - return s.toString(); - } - - /** Assert that the Now Playing list is a particular value */ - private void assertNowPlayingList(List<AvrcpItem> expected) { - List<AvrcpItem> current = getNowPlayingList(); - String err = - "Now playing list incorrect, expected=" - + avrcpItemListToString(expected) - + ", actual=" - + avrcpItemListToString(current); - Assert.assertEquals(err, expected.size(), current.size()); - for (int i = 0; i < expected.size(); i++) { - Assert.assertEquals(err, expected.get(i), current.get(i)); - } + assertThat(getNowPlayingList()).containsExactlyElementsIn(nowPlayingList).inOrder(); } /** @@ -387,19 +355,19 @@ public class AvrcpControllerStateMachineTest { numBroadcastsSent += 2; verify(mAvrcpControllerService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)) .sendBroadcast(mIntentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertEquals( - mTestDevice, - mIntentArgument.getValue().getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals( - BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED, - mIntentArgument.getValue().getAction()); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mIntentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertThat( - mAvrcpStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class)); - Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_DISCONNECTED); + assertThat( + mIntentArgument + .getValue() + .getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(mTestDevice); + assertThat(mIntentArgument.getValue().getAction()) + .isEqualTo(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); + assertThat(mIntentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mAvrcpStateMachine.getCurrentState()) + .isInstanceOf(AvrcpControllerStateMachine.Disconnected.class); + assertThat(mAvrcpStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine)); } @@ -410,26 +378,25 @@ public class AvrcpControllerStateMachineTest { MediaControllerCompat.TransportControls transportControls = BluetoothMediaBrowserService.getTransportControls(); assertThat(transportControls).isNotNull(); - Assert.assertEquals( - PlaybackStateCompat.STATE_NONE, - BluetoothMediaBrowserService.getPlaybackState().getState()); + assertThat(BluetoothMediaBrowserService.getPlaybackState().getState()) + .isEqualTo(PlaybackStateCompat.STATE_NONE); mAvrcpStateMachine.disconnect(); numBroadcastsSent += 2; verify(mAvrcpControllerService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)) .sendBroadcast(mIntentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertEquals( - mTestDevice, - mIntentArgument.getValue().getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals( - BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED, - mIntentArgument.getValue().getAction()); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mIntentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertThat( - mAvrcpStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class)); - Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_DISCONNECTED); + assertThat( + mIntentArgument + .getValue() + .getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(mTestDevice); + assertThat(mIntentArgument.getValue().getAction()) + .isEqualTo(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); + assertThat(mIntentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mAvrcpStateMachine.getCurrentState()) + .isInstanceOf(AvrcpControllerStateMachine.Disconnected.class); + assertThat(mAvrcpStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine)); } @@ -437,29 +404,28 @@ public class AvrcpControllerStateMachineTest { @Test @FlakyTest public void testBrowsingOnly() { - Assert.assertEquals(0, mAvrcpControllerService.sBrowseTree.mRootNode.getChildrenCount()); + assertThat(mAvrcpControllerService.sBrowseTree.mRootNode.getChildrenCount()).isEqualTo(0); int numBroadcastsSent = setUpConnectedState(false, true); - Assert.assertEquals(1, mAvrcpControllerService.sBrowseTree.mRootNode.getChildrenCount()); - Assert.assertEquals( - PlaybackStateCompat.STATE_NONE, - BluetoothMediaBrowserService.getPlaybackState().getState()); + assertThat(mAvrcpControllerService.sBrowseTree.mRootNode.getChildrenCount()).isEqualTo(1); + assertThat(BluetoothMediaBrowserService.getPlaybackState().getState()) + .isEqualTo(PlaybackStateCompat.STATE_NONE); mAvrcpStateMachine.disconnect(); numBroadcastsSent += 2; verify(mAvrcpControllerService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)) .sendBroadcast(mIntentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertEquals( - mTestDevice, - mIntentArgument.getValue().getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals( - BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED, - mIntentArgument.getValue().getAction()); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mIntentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertThat( - mAvrcpStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(AvrcpControllerStateMachine.Disconnected.class)); - Assert.assertEquals(mAvrcpStateMachine.getState(), BluetoothProfile.STATE_DISCONNECTED); + assertThat( + mIntentArgument + .getValue() + .getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(mTestDevice); + assertThat(mIntentArgument.getValue().getAction()) + .isEqualTo(BluetoothAvrcpController.ACTION_CONNECTION_STATE_CHANGED); + assertThat(mIntentArgument.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mAvrcpStateMachine.getCurrentState()) + .isInstanceOf(AvrcpControllerStateMachine.Disconnected.class); + assertThat(mAvrcpStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); verify(mAvrcpControllerService).removeStateMachine(eq(mAvrcpStateMachine)); } @@ -478,7 +444,7 @@ public class AvrcpControllerStateMachineTest { /** Test to make sure the state machine is tracking the correct device */ @Test public void testGetDevice() { - Assert.assertEquals(mAvrcpStateMachine.getDevice(), mTestDevice); + assertThat(mAvrcpStateMachine.getDevice()).isEqualTo(mTestDevice); } /** Test that dumpsys will generate information about connected devices */ @@ -724,10 +690,9 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Verify that the player object is available. - Assert.assertEquals(true, results.isCached()); - Assert.assertEquals( - "MediaItem{mFlags=1, mDescription=" + playerName + ", null, null}", - results.getChildren().get(0).getMediaItem().toString()); + assertThat(results.isCached()).isTrue(); + assertThat(results.getChildren().get(0).getMediaItem().toString()) + .isEqualTo("MediaItem{mFlags=1, mDescription=" + playerName + ", null, null}"); // Fetch contents of that player object BrowseTree.BrowseNode playerOneNode = @@ -806,13 +771,13 @@ public class AvrcpControllerStateMachineTest { assertThat(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()).isTrue(); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); assertThat(players.contains(mAvrcpStateMachine.getAddressedPlayerId())).isTrue(); - Assert.assertEquals(testPlayers.size(), players.size()); + assertThat(players.size()).isEqualTo(testPlayers.size()); for (AvrcpPlayer player : testPlayers) { assertThat(players.contains(player.getId())).isTrue(); } // Verify we request metadata, playback state and now playing list - assertNowPlayingList(new ArrayList<AvrcpItem>()); + assertThat(getNowPlayingList()).isEmpty(); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getNowPlayingList(eq(mTestAddress), eq(0), eq(19)); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) @@ -858,7 +823,7 @@ public class AvrcpControllerStateMachineTest { assertThat(mAvrcpStateMachine.mBrowseTree.mRootNode.isCached()).isTrue(); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); assertThat(players.contains(mAvrcpStateMachine.getAddressedPlayerId())).isTrue(); - Assert.assertEquals(testPlayers.size() + 1, players.size()); + assertThat(players.size()).isEqualTo(testPlayers.size() + 1); for (AvrcpPlayer player : testPlayers) { assertThat(players.contains(player.getId())).isTrue(); } @@ -913,12 +878,12 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // The addressed player should always be in the available player set - Assert.assertEquals(2, mAvrcpStateMachine.getAddressedPlayerId()); + assertThat(mAvrcpStateMachine.getAddressedPlayerId()).isEqualTo(2); SparseArray<AvrcpPlayer> players = mAvrcpStateMachine.getAvailablePlayers(); assertThat(players.contains(mAvrcpStateMachine.getAddressedPlayerId())).isTrue(); // Make sure the Now Playing list is now cleared - assertNowPlayingList(new ArrayList<AvrcpItem>()); + assertThat(getNowPlayingList()).isEmpty(); // Verify that a player change to a player with Now Playing support causes a refresh. verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) @@ -967,7 +932,7 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Make sure the Now Playing list is now cleared and we requested metadata - assertNowPlayingList(new ArrayList<AvrcpItem>()); + assertThat(getNowPlayingList()).isEmpty(); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) .getCurrentMetadata(eq(mTestAddress)); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) @@ -1256,24 +1221,24 @@ public class AvrcpControllerStateMachineTest { MediaMetadataCompat metadata = controller.getMetadata(); assertThat(metadata).isNotNull(); - Assert.assertEquals("title", metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)); - Assert.assertEquals("artist", metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)); - Assert.assertEquals("album", metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)); - Assert.assertEquals(1, metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)); - Assert.assertEquals(10, metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)); - Assert.assertEquals("none", metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)); - Assert.assertEquals(10, metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)).isEqualTo("title"); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)).isEqualTo("artist"); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)).isEqualTo("album"); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)).isEqualTo(1); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)).isEqualTo(10); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)).isEqualTo("none"); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)).isEqualTo(10); PlaybackStateCompat playbackState = controller.getPlaybackState(); assertThat(playbackState).isNotNull(); - Assert.assertEquals(PlaybackStateCompat.STATE_PAUSED, playbackState.getState()); - Assert.assertEquals(7, playbackState.getPosition()); + assertThat(playbackState.getState()).isEqualTo(PlaybackStateCompat.STATE_PAUSED); + assertThat(playbackState.getPosition()).isEqualTo(7); List<MediaSessionCompat.QueueItem> queue = controller.getQueue(); assertThat(queue).isNotNull(); - Assert.assertEquals(2, queue.size()); - Assert.assertEquals("title", queue.get(0).getDescription().getTitle().toString()); - Assert.assertEquals("title 2", queue.get(1).getDescription().getTitle().toString()); + assertThat(queue.size()).isEqualTo(2); + assertThat(queue.get(0).getDescription().getTitle().toString()).isEqualTo("title"); + assertThat(queue.get(1).getDescription().getTitle().toString()).isEqualTo("title 2"); } /** Test becoming inactive from the active state */ @@ -1323,18 +1288,18 @@ public class AvrcpControllerStateMachineTest { MediaMetadataCompat metadata = controller.getMetadata(); assertThat(metadata).isNotNull(); - Assert.assertEquals("Song 1", metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)); - Assert.assertEquals("artist", metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)); - Assert.assertEquals("album", metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)); - Assert.assertEquals(1, metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)); - Assert.assertEquals(2, metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)); - Assert.assertEquals("none", metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)); - Assert.assertEquals(10, metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)).isEqualTo("Song 1"); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)).isEqualTo("artist"); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)).isEqualTo("album"); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)).isEqualTo(1); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)).isEqualTo(2); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)).isEqualTo("none"); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)).isEqualTo(10); PlaybackStateCompat playbackState = controller.getPlaybackState(); assertThat(playbackState).isNotNull(); - Assert.assertEquals(PlaybackStateCompat.STATE_PLAYING, playbackState.getState()); - Assert.assertEquals(0, playbackState.getActiveQueueItemId()); + assertThat(playbackState.getState()).isEqualTo(PlaybackStateCompat.STATE_PLAYING); + assertThat(playbackState.getActiveQueueItemId()).isEqualTo(0); // Track changes, with new metadata and new track number track = makeTrack("Song 2", "artist", "album", 2, 2, "none", 10, null); @@ -1344,18 +1309,18 @@ public class AvrcpControllerStateMachineTest { // Assert new track metadata and active queue item metadata = controller.getMetadata(); assertThat(metadata).isNotNull(); - Assert.assertEquals("Song 2", metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)); - Assert.assertEquals("artist", metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)); - Assert.assertEquals("album", metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)); - Assert.assertEquals(2, metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)); - Assert.assertEquals(2, metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)); - Assert.assertEquals("none", metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)); - Assert.assertEquals(10, metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)).isEqualTo("Song 2"); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)).isEqualTo("artist"); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)).isEqualTo("album"); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)).isEqualTo(2); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)).isEqualTo(2); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)).isEqualTo("none"); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)).isEqualTo(10); playbackState = controller.getPlaybackState(); assertThat(playbackState).isNotNull(); - Assert.assertEquals(PlaybackStateCompat.STATE_PLAYING, playbackState.getState()); - Assert.assertEquals(1, playbackState.getActiveQueueItemId()); + assertThat(playbackState.getState()).isEqualTo(PlaybackStateCompat.STATE_PLAYING); + assertThat(playbackState.getActiveQueueItemId()).isEqualTo(1); } /** Test receiving a track change update when we're not the active device */ @@ -1405,9 +1370,8 @@ public class AvrcpControllerStateMachineTest { eq(AvrcpControllerService.PASS_THRU_CMD_ID_PAUSE), eq(KEY_DOWN)); verify(mA2dpSinkService, never()).requestAudioFocus(mTestDevice, true); - Assert.assertEquals( - PlaybackStateCompat.STATE_ERROR, - BluetoothMediaBrowserService.getPlaybackState().getState()); + assertThat(BluetoothMediaBrowserService.getPlaybackState().getState()) + .isEqualTo(PlaybackStateCompat.STATE_ERROR); } /** Test receiving a play position update when we're not the active device */ @@ -1433,7 +1397,7 @@ public class AvrcpControllerStateMachineTest { PlaybackStateCompat playbackState = controller.getPlaybackState(); assertThat(playbackState).isNotNull(); - Assert.assertEquals(0, playbackState.getPosition()); + assertThat(playbackState.getPosition()).isEqualTo(0); } /** Test receiving a now playing list update when we're not the active device */ @@ -1771,7 +1735,7 @@ public class AvrcpControllerStateMachineTest { // Make sure its set by re grabbing the node and checking its contents are cached nowPlaying = mAvrcpStateMachine.findNode("NOW_PLAYING"); assertThat(nowPlaying.isCached()).isTrue(); - assertNowPlayingList(updatedNowPlayingList); + assertThat(getNowPlayingList()).containsExactlyElementsIn(updatedNowPlayingList).inOrder(); } /** @@ -1831,7 +1795,7 @@ public class AvrcpControllerStateMachineTest { // Make sure its set by re grabbing the node and checking its contents are cached nowPlaying = mAvrcpStateMachine.findNode("NOW_PLAYING"); assertThat(nowPlaying.isCached()).isTrue(); - assertNowPlayingList(updatedNowPlayingList); + assertThat(getNowPlayingList()).containsExactlyElementsIn(updatedNowPlayingList).inOrder(); } /** @@ -1899,7 +1863,7 @@ public class AvrcpControllerStateMachineTest { // Make sure its set by re grabbing the node and checking its contents are cached nowPlaying = mAvrcpStateMachine.findNode("NOW_PLAYING"); assertThat(nowPlaying.isCached()).isTrue(); - assertNowPlayingList(updatedNowPlayingList); + assertThat(getNowPlayingList()).containsExactlyElementsIn(updatedNowPlayingList).inOrder(); } /** @@ -1964,7 +1928,7 @@ public class AvrcpControllerStateMachineTest { // Make sure its set by re grabbing the node and checking its contents are cached nowPlaying = mAvrcpStateMachine.findNode("NOW_PLAYING"); assertThat(nowPlaying.isCached()).isTrue(); - assertNowPlayingList(updatedNowPlayingList); + assertThat(getNowPlayingList()).containsExactlyElementsIn(updatedNowPlayingList).inOrder(); } /** @@ -1997,7 +1961,8 @@ public class AvrcpControllerStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mAvrcpStateMachine.getHandler().getLooper()); // Node should be set to cached and notified on - assertNowPlayingList(new ArrayList<AvrcpItem>()); + assertThat(getNowPlayingList()).isEmpty(); + assertThat(nowPlaying.isCached()).isTrue(); // See that state from BluetoothMediaBrowserService is updated to null (i.e. empty) diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java index 6cf6bb466b..37db2a87bb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java @@ -32,7 +32,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -95,7 +94,7 @@ public final class AvrcpCoverArtStorageTest { Uri uri = mAvrcpCoverArtStorage.addImage(mDevice1, mHandle1, mImage1); - Assert.assertEquals(expectedUri, uri); + assertThat(uri).isEqualTo(expectedUri); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isTrue(); } @@ -106,12 +105,12 @@ public final class AvrcpCoverArtStorageTest { Uri uri = mAvrcpCoverArtStorage.addImage(mDevice1, mHandle1, mImage1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isTrue(); - Assert.assertEquals(expectedUri, uri); + assertThat(uri).isEqualTo(expectedUri); assertImageSame(mImage1, mDevice1, mHandle1); uri = mAvrcpCoverArtStorage.addImage(mDevice1, mHandle1, mImage2); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isTrue(); - Assert.assertEquals(expectedUri, uri); + assertThat(uri).isEqualTo(expectedUri); assertImageSame(mImage2, mDevice1, mHandle1); } @@ -126,10 +125,10 @@ public final class AvrcpCoverArtStorageTest { Uri uri2 = mAvrcpCoverArtStorage.addImage(mDevice1, mHandle2, mImage2); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isTrue(); - Assert.assertEquals(expectedUri1, uri1); + assertThat(uri1).isEqualTo(expectedUri1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle2)).isTrue(); - Assert.assertEquals(expectedUri2, uri2); + assertThat(uri2).isEqualTo(expectedUri2); } @Test @@ -143,38 +142,38 @@ public final class AvrcpCoverArtStorageTest { Uri uri2 = mAvrcpCoverArtStorage.addImage(mDevice2, mHandle1, mImage1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isTrue(); - Assert.assertEquals(expectedUri1, uri1); + assertThat(uri1).isEqualTo(expectedUri1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isTrue(); - Assert.assertEquals(expectedUri2, uri2); + assertThat(uri2).isEqualTo(expectedUri2); } @Test public void addNullImage_imageNotAdded() { Uri uri = mAvrcpCoverArtStorage.addImage(mDevice1, mHandle1, null); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); - Assert.assertEquals(null, uri); + assertThat(uri).isNull(); } @Test public void addImageNullDevice_imageNotAdded() { Uri uri = mAvrcpCoverArtStorage.addImage(null, mHandle1, mImage1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); - Assert.assertEquals(null, uri); + assertThat(uri).isNull(); } @Test public void addImageNullHandle_imageNotAdded() { Uri uri = mAvrcpCoverArtStorage.addImage(mDevice1, null, mImage1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); - Assert.assertEquals(null, uri); + assertThat(uri).isNull(); } @Test public void addImageEmptyHandle_imageNotAdded() { Uri uri = mAvrcpCoverArtStorage.addImage(mDevice1, "", mImage1); assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); - Assert.assertEquals(null, uri); + assertThat(uri).isNull(); } @Test @@ -198,28 +197,28 @@ public final class AvrcpCoverArtStorageTest { public void getImageThatDoesntExist_returnsNull() { assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); Bitmap image = mAvrcpCoverArtStorage.getImage(mDevice1, mHandle1); - Assert.assertEquals(null, image); + assertThat(image).isNull(); } @Test public void getImageNullDevice_returnsNull() { assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); Bitmap image = mAvrcpCoverArtStorage.getImage(null, mHandle1); - Assert.assertEquals(null, image); + assertThat(image).isNull(); } @Test public void getImageNullHandle_returnsNull() { assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); Bitmap image = mAvrcpCoverArtStorage.getImage(mDevice1, null); - Assert.assertEquals(null, image); + assertThat(image).isNull(); } @Test public void getImageEmptyHandle_returnsNull() { assertThat(mAvrcpCoverArtStorage.doesImageExist(mDevice1, mHandle1)).isFalse(); Bitmap image = mAvrcpCoverArtStorage.getImage(mDevice1, ""); - Assert.assertEquals(null, image); + assertThat(image).isNull(); } @Test @@ -344,6 +343,6 @@ public final class AvrcpCoverArtStorageTest { mAvrcpCoverArtStorage.addImage(mDevice1, mHandle1, mImage1); - Assert.assertEquals(expectedString, mAvrcpCoverArtStorage.toString()); + assertThat(mAvrcpCoverArtStorage.toString()).isEqualTo(expectedString); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java index 7a296cd075..9e77c640d2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java @@ -29,7 +29,6 @@ import android.support.v4.media.MediaMetadataCompat; import androidx.test.runner.AndroidJUnit4; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -92,19 +91,19 @@ public final class AvrcpItemTest { AvrcpItem item = builder.build(); - Assert.assertEquals(mDevice, item.getDevice()); - Assert.assertEquals(true, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(UUID, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(trackNumber, item.getTrackNumber()); - Assert.assertEquals(totalTracks, item.getTotalNumberOfTracks()); - Assert.assertEquals(artHandle, item.getCoverArtHandle()); - Assert.assertEquals(uri, item.getCoverArtLocation()); + assertThat(item.getDevice()).isEqualTo(mDevice); + assertThat(item.isPlayable()).isTrue(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isEqualTo(UUID); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(trackNumber); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(totalTracks); + assertThat(item.getCoverArtHandle()).isEqualTo(artHandle); + assertThat(item.getCoverArtLocation()).isEqualTo(uri); } @Test @@ -139,19 +138,19 @@ public final class AvrcpItemTest { builder.fromAvrcpAttributeArray(attrIds, attrMap); AvrcpItem item = builder.build(); - Assert.assertEquals(null, item.getDevice()); - Assert.assertEquals(false, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(null, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(1, item.getTrackNumber()); - Assert.assertEquals(12, item.getTotalNumberOfTracks()); - Assert.assertEquals(artHandle, item.getCoverArtHandle()); - Assert.assertEquals(null, item.getCoverArtLocation()); + assertThat(item.getDevice()).isNull(); + assertThat(item.isPlayable()).isFalse(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isNull(); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(1); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(12); + assertThat(item.getCoverArtHandle()).isEqualTo(artHandle); + assertThat(item.getCoverArtLocation()).isNull(); } @Test @@ -201,19 +200,19 @@ public final class AvrcpItemTest { builder.fromAvrcpAttributeArray(attrIds, attrMap); AvrcpItem item = builder.build(); - Assert.assertEquals(null, item.getDevice()); - Assert.assertEquals(false, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(null, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(1, item.getTrackNumber()); - Assert.assertEquals(12, item.getTotalNumberOfTracks()); - Assert.assertEquals(artHandle, item.getCoverArtHandle()); - Assert.assertEquals(null, item.getCoverArtLocation()); + assertThat(item.getDevice()).isNull(); + assertThat(item.isPlayable()).isFalse(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isNull(); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(1); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(12); + assertThat(item.getCoverArtHandle()).isEqualTo(artHandle); + assertThat(item.getCoverArtLocation()).isNull(); } @Test @@ -248,19 +247,19 @@ public final class AvrcpItemTest { builder.fromAvrcpAttributeArray(attrIds, attrMap); AvrcpItem item = builder.build(); - Assert.assertEquals(null, item.getDevice()); - Assert.assertEquals(false, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(null, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(1, item.getTrackNumber()); - Assert.assertEquals(12, item.getTotalNumberOfTracks()); - Assert.assertEquals(null, item.getCoverArtHandle()); - Assert.assertEquals(null, item.getCoverArtLocation()); + assertThat(item.getDevice()).isNull(); + assertThat(item.isPlayable()).isFalse(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isNull(); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(1); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(12); + assertThat(item.getCoverArtHandle()).isNull(); + assertThat(item.getCoverArtLocation()).isNull(); } @Test @@ -295,19 +294,19 @@ public final class AvrcpItemTest { builder.fromAvrcpAttributeArray(attrIds, attrMap); AvrcpItem item = builder.build(); - Assert.assertEquals(null, item.getDevice()); - Assert.assertEquals(false, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(null, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(1, item.getTrackNumber()); - Assert.assertEquals(12, item.getTotalNumberOfTracks()); - Assert.assertEquals(null, item.getCoverArtHandle()); - Assert.assertEquals(null, item.getCoverArtLocation()); + assertThat(item.getDevice()).isNull(); + assertThat(item.isPlayable()).isFalse(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isNull(); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(1); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(12); + assertThat(item.getCoverArtHandle()).isNull(); + assertThat(item.getCoverArtLocation()).isNull(); } @Test @@ -342,19 +341,19 @@ public final class AvrcpItemTest { builder.fromAvrcpAttributeArray(attrIds, attrMap); AvrcpItem item = builder.build(); - Assert.assertEquals(null, item.getDevice()); - Assert.assertEquals(false, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(null, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(1, item.getTrackNumber()); - Assert.assertEquals(12, item.getTotalNumberOfTracks()); - Assert.assertEquals(null, item.getCoverArtHandle()); - Assert.assertEquals(null, item.getCoverArtLocation()); + assertThat(item.getDevice()).isNull(); + assertThat(item.isPlayable()).isFalse(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isNull(); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(1); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(12); + assertThat(item.getCoverArtHandle()).isNull(); + assertThat(item.getCoverArtLocation()).isNull(); } @Test @@ -389,19 +388,19 @@ public final class AvrcpItemTest { builder.fromAvrcpAttributeArray(attrIds, attrMap); AvrcpItem item = builder.build(); - Assert.assertEquals(null, item.getDevice()); - Assert.assertEquals(false, item.isPlayable()); - Assert.assertEquals(false, item.isBrowsable()); - Assert.assertEquals(0, item.getUid()); - Assert.assertEquals(null, item.getUuid()); - Assert.assertEquals(null, item.getDisplayableName()); - Assert.assertEquals(title, item.getTitle()); - Assert.assertEquals(artist, item.getArtistName()); - Assert.assertEquals(album, item.getAlbumName()); - Assert.assertEquals(1, item.getTrackNumber()); - Assert.assertEquals(12, item.getTotalNumberOfTracks()); - Assert.assertEquals(null, item.getCoverArtHandle()); - Assert.assertEquals(null, item.getCoverArtLocation()); + assertThat(item.getDevice()).isNull(); + assertThat(item.isPlayable()).isFalse(); + assertThat(item.isBrowsable()).isFalse(); + assertThat(item.getUid()).isEqualTo(0); + assertThat(item.getUuid()).isNull(); + assertThat(item.getDisplayableName()).isNull(); + assertThat(item.getTitle()).isEqualTo(title); + assertThat(item.getArtistName()).isEqualTo(artist); + assertThat(item.getAlbumName()).isEqualTo(album); + assertThat(item.getTrackNumber()).isEqualTo(1); + assertThat(item.getTotalNumberOfTracks()).isEqualTo(12); + assertThat(item.getCoverArtHandle()).isNull(); + assertThat(item.getCoverArtLocation()).isNull(); } @Test @@ -413,10 +412,10 @@ public final class AvrcpItemTest { builder.setCoverArtLocation(uri); AvrcpItem item = builder.build(); - Assert.assertEquals(uri, item.getCoverArtLocation()); + assertThat(item.getCoverArtLocation()).isEqualTo(uri); item.setCoverArtLocation(uri2); - Assert.assertEquals(uri2, item.getCoverArtLocation()); + assertThat(item.getCoverArtLocation()).isEqualTo(uri2); } @Test @@ -452,30 +451,28 @@ public final class AvrcpItemTest { AvrcpItem item = builder.build(); MediaMetadataCompat metadata = item.toMediaMetadata(); - Assert.assertEquals(UUID, metadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)); - Assert.assertEquals( - title, metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)); - Assert.assertEquals(title, metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)); - Assert.assertEquals(artist, metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)); - Assert.assertEquals(album, metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)); - Assert.assertEquals( - trackNumber, metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)); - Assert.assertEquals( - totalTracks, metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)); - Assert.assertEquals(genre, metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)); - Assert.assertEquals( - playingTime, metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)); - Assert.assertEquals( - uri, - Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI))); - Assert.assertEquals( - uri, Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ART_URI))); - Assert.assertEquals( - uri, Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI))); - Assert.assertEquals( - null, metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON)); - Assert.assertEquals(null, metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ART)); - Assert.assertEquals(null, metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART)); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)).isEqualTo(UUID); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) + .isEqualTo(title); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)).isEqualTo(title); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)).isEqualTo(artist); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)).isEqualTo(album); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER)) + .isEqualTo(trackNumber); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)) + .isEqualTo(totalTracks); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)).isEqualTo(genre); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)) + .isEqualTo(playingTime); + assertThat(Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI))) + .isEqualTo(uri); + assertThat(Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ART_URI))) + .isEqualTo(uri); + assertThat(Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI))) + .isEqualTo(uri); + assertThat(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON)).isNull(); + assertThat(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ART)).isNull(); + assertThat(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART)).isNull(); assertThat(metadata.containsKey(MediaMetadataCompat.METADATA_KEY_BT_FOLDER_TYPE)).isFalse(); } @@ -507,30 +504,28 @@ public final class AvrcpItemTest { AvrcpItem item = builder.build(); MediaMetadataCompat metadata = item.toMediaMetadata(); - Assert.assertEquals(UUID, metadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)); - Assert.assertEquals( - title, metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)); - Assert.assertEquals(title, metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)); - Assert.assertEquals(artist, metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)); - Assert.assertEquals(null, metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)); - Assert.assertEquals( - totalTracks, metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)); - Assert.assertEquals(genre, metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)); - Assert.assertEquals( - playingTime, metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)); - Assert.assertEquals( - uri, - Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI))); - Assert.assertEquals( - uri, Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ART_URI))); - Assert.assertEquals( - uri, Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI))); - Assert.assertEquals( - null, metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON)); - Assert.assertEquals(null, metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ART)); - Assert.assertEquals(null, metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART)); - Assert.assertEquals( - type, metadata.getLong(MediaMetadataCompat.METADATA_KEY_BT_FOLDER_TYPE)); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)).isEqualTo(UUID); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE)) + .isEqualTo(title); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE)).isEqualTo(title); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST)).isEqualTo(artist); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM)).isNull(); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS)) + .isEqualTo(totalTracks); + assertThat(metadata.getString(MediaMetadataCompat.METADATA_KEY_GENRE)).isEqualTo(genre); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION)) + .isEqualTo(playingTime); + assertThat(Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI))) + .isEqualTo(uri); + assertThat(Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ART_URI))) + .isEqualTo(uri); + assertThat(Uri.parse(metadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI))) + .isEqualTo(uri); + assertThat(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON)).isNull(); + assertThat(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ART)).isNull(); + assertThat(metadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART)).isNull(); + assertThat(metadata.getLong(MediaMetadataCompat.METADATA_KEY_BT_FOLDER_TYPE)) + .isEqualTo(type); } @Test @@ -550,14 +545,14 @@ public final class AvrcpItemTest { assertThat(mediaItem.isPlayable()).isTrue(); assertThat(mediaItem.isBrowsable()).isFalse(); - Assert.assertEquals(UUID, mediaItem.getMediaId()); + assertThat(mediaItem.getMediaId()).isEqualTo(UUID); - Assert.assertEquals(UUID, desc.getMediaId()); - Assert.assertEquals(null, desc.getMediaUri()); - Assert.assertEquals(title, desc.getTitle().toString()); + assertThat(desc.getMediaId()).isEqualTo(UUID); + assertThat(desc.getMediaUri()).isNull(); + assertThat(desc.getTitle().toString()).isEqualTo(title); assertThat(desc.getSubtitle()).isNull(); - Assert.assertEquals(uri, desc.getIconUri()); - Assert.assertEquals(null, desc.getIconBitmap()); + assertThat(desc.getIconUri()).isEqualTo(uri); + assertThat(desc.getIconBitmap()).isNull(); } @Test @@ -579,14 +574,14 @@ public final class AvrcpItemTest { assertThat(mediaItem.isPlayable()).isTrue(); assertThat(mediaItem.isBrowsable()).isFalse(); - Assert.assertEquals(UUID, mediaItem.getMediaId()); + assertThat(mediaItem.getMediaId()).isEqualTo(UUID); - Assert.assertEquals(UUID, desc.getMediaId()); - Assert.assertEquals(null, desc.getMediaUri()); - Assert.assertEquals(displayName, desc.getTitle().toString()); + assertThat(desc.getMediaId()).isEqualTo(UUID); + assertThat(desc.getMediaUri()).isNull(); + assertThat(desc.getTitle().toString()).isEqualTo(displayName); assertThat(desc.getSubtitle()).isNull(); - Assert.assertEquals(uri, desc.getIconUri()); - Assert.assertEquals(null, desc.getIconBitmap()); + assertThat(desc.getIconUri()).isEqualTo(uri); + assertThat(desc.getIconBitmap()).isNull(); } @Test @@ -606,14 +601,14 @@ public final class AvrcpItemTest { assertThat(mediaItem.isPlayable()).isFalse(); assertThat(mediaItem.isBrowsable()).isTrue(); - Assert.assertEquals(UUID, mediaItem.getMediaId()); + assertThat(mediaItem.getMediaId()).isEqualTo(UUID); - Assert.assertEquals(UUID, desc.getMediaId()); - Assert.assertEquals(null, desc.getMediaUri()); - Assert.assertEquals(title, desc.getTitle().toString()); + assertThat(desc.getMediaId()).isEqualTo(UUID); + assertThat(desc.getMediaUri()).isNull(); + assertThat(desc.getTitle().toString()).isEqualTo(title); assertThat(desc.getSubtitle()).isNull(); - Assert.assertEquals(uri, desc.getIconUri()); - Assert.assertEquals(null, desc.getIconBitmap()); + assertThat(desc.getIconUri()).isEqualTo(uri); + assertThat(desc.getIconBitmap()).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java index 275b39452d..16c43583e6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java @@ -47,7 +47,7 @@ public class BrowseTreeTest { public void constructor_withoutDevice() { BrowseTree browseTree = new BrowseTree(null); - assertThat(browseTree.mRootNode.mItem.getDevice()).isEqualTo(null); + assertThat(browseTree.mRootNode.mItem.getDevice()).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java index c4ae402379..3500d0e0c7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java @@ -22,7 +22,6 @@ import android.annotation.SuppressLint; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -63,23 +62,23 @@ public class BipAttachmentFormatTest { int expectedSize = (size != null ? Integer.parseInt(size) : -1); BipAttachmentFormat attachment = new BipAttachmentFormat(contentType, charset, name, size, created, modified); - Assert.assertEquals(contentType, attachment.getContentType()); - Assert.assertEquals(charset, attachment.getCharset()); - Assert.assertEquals(name, attachment.getName()); - Assert.assertEquals(expectedSize, attachment.getSize()); + assertThat(attachment.getContentType()).isEqualTo(contentType); + assertThat(attachment.getCharset()).isEqualTo(charset); + assertThat(attachment.getName()).isEqualTo(name); + assertThat(attachment.getSize()).isEqualTo(expectedSize); if (expectedCreated != null) { - Assert.assertEquals(expectedCreated, attachment.getCreatedDate().getTime()); - Assert.assertEquals(isCreatedUtc, attachment.getCreatedDate().isUtc()); + assertThat(attachment.getCreatedDate().getTime()).isEqualTo(expectedCreated); + assertThat(attachment.getCreatedDate().isUtc()).isEqualTo(isCreatedUtc); } else { - Assert.assertEquals(null, attachment.getCreatedDate()); + assertThat(attachment.getCreatedDate()).isNull(); } if (expectedModified != null) { - Assert.assertEquals(expectedModified, attachment.getModifiedDate().getTime()); - Assert.assertEquals(isModifiedUtc, attachment.getModifiedDate().isUtc()); + assertThat(attachment.getModifiedDate().getTime()).isEqualTo(expectedModified); + assertThat(attachment.getModifiedDate().isUtc()).isEqualTo(isModifiedUtc); } else { - Assert.assertEquals(null, attachment.getModifiedDate()); + assertThat(attachment.getModifiedDate()).isNull(); } } @@ -93,23 +92,23 @@ public class BipAttachmentFormatTest { Date modified) { BipAttachmentFormat attachment = new BipAttachmentFormat(contentType, charset, name, size, created, modified); - Assert.assertEquals(contentType, attachment.getContentType()); - Assert.assertEquals(charset, attachment.getCharset()); - Assert.assertEquals(name, attachment.getName()); - Assert.assertEquals(size, attachment.getSize()); + assertThat(attachment.getContentType()).isEqualTo(contentType); + assertThat(attachment.getCharset()).isEqualTo(charset); + assertThat(attachment.getName()).isEqualTo(name); + assertThat(attachment.getSize()).isEqualTo(size); if (created != null) { - Assert.assertEquals(created, attachment.getCreatedDate().getTime()); + assertThat(attachment.getCreatedDate().getTime()).isEqualTo(created); assertThat(attachment.getCreatedDate().isUtc()).isTrue(); } else { - Assert.assertEquals(null, attachment.getCreatedDate()); + assertThat(attachment.getCreatedDate()).isNull(); } if (modified != null) { - Assert.assertEquals(modified, attachment.getModifiedDate().getTime()); + assertThat(attachment.getModifiedDate().getTime()).isEqualTo(modified); assertThat(attachment.getModifiedDate().isUtc()).isTrue(); } else { - Assert.assertEquals(null, attachment.getModifiedDate()); + assertThat(attachment.getModifiedDate()).isNull(); } } @@ -326,7 +325,7 @@ public class BipAttachmentFormatTest { "2048", "19900101T123456", "19900101T123456"); - Assert.assertEquals(expected, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expected); // Create by parsing, all fields with utc dates attachment = @@ -337,31 +336,31 @@ public class BipAttachmentFormatTest { "2048", "19900101T123456Z", "19900101T123456Z"); - Assert.assertEquals(expectedUtc, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedUtc); // Create by parsing, no timestamps attachment = new BipAttachmentFormat( "text/plain", "ISO-8859-1", "thisisatextfile.txt", "2048", null, null); - Assert.assertEquals(expectedNoDates, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedNoDates); // Create by parsing, no size, no dates attachment = new BipAttachmentFormat( "text/plain", "ISO-8859-1", "thisisatextfile.txt", null, null, null); - Assert.assertEquals(expectedNoSizeNoDates, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedNoSizeNoDates); // Create by parsing, no charset, no dates attachment = new BipAttachmentFormat( "text/plain", null, "thisisatextfile.txt", "2048", null, null); - Assert.assertEquals(expectedNoCharsetNoDates, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedNoCharsetNoDates); // Create by parsing, content type only attachment = new BipAttachmentFormat( "text/plain", null, "thisisatextfile.txt", null, null, null); - Assert.assertEquals(expectedRequiredOnly, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedRequiredOnly); } @Test @@ -395,30 +394,30 @@ public class BipAttachmentFormatTest { BipAttachmentFormat attachment = new BipAttachmentFormat( "text/plain", "ISO-8859-1", "thisisatextfile.txt", 2048, date, date); - Assert.assertEquals(expected, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expected); // Create with objects, no dates attachment = new BipAttachmentFormat( "text/plain", "ISO-8859-1", "thisisatextfile.txt", 2048, null, null); - Assert.assertEquals(expectedNoDates, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedNoDates); // Create with objects, no size and no dates attachment = new BipAttachmentFormat( "text/plain", "ISO-8859-1", "thisisatextfile.txt", -1, null, null); - Assert.assertEquals(expectedNoSizeNoDates, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedNoSizeNoDates); // Create with objects, no charset, no dates attachment = new BipAttachmentFormat( "text/plain", null, "thisisatextfile.txt", 2048, null, null); - Assert.assertEquals(expectedNoCharsetNoDates, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedNoCharsetNoDates); // Create with objects, content type only attachment = new BipAttachmentFormat("text/plain", null, "thisisatextfile.txt", -1, null, null); - Assert.assertEquals(expectedRequiredOnly, attachment.toString()); + assertThat(attachment.toString()).isEqualTo(expectedRequiredOnly); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java index 33937d8741..9b3032c657 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java @@ -22,7 +22,6 @@ import android.annotation.SuppressLint; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,17 +66,17 @@ public class BipDatetimeTest { @SuppressLint("UndefinedEquals") private void testParse(String date, Date expectedDate, boolean isUtc, String expectedStr) { BipDateTime bipDateTime = new BipDateTime(date); - Assert.assertEquals(expectedDate, bipDateTime.getTime()); - Assert.assertEquals(isUtc, bipDateTime.isUtc()); - Assert.assertEquals(expectedStr, bipDateTime.toString()); + assertThat(bipDateTime.getTime()).isEqualTo(expectedDate); + assertThat(bipDateTime.isUtc()).isEqualTo(isUtc); + assertThat(bipDateTime.toString()).isEqualTo(expectedStr); } @SuppressLint("UndefinedEquals") private void testCreate(Date date, String dateStr) { BipDateTime bipDate = new BipDateTime(date); - Assert.assertEquals(date, bipDate.getTime()); + assertThat(bipDate.getTime()).isEqualTo(date); assertThat(bipDate.isUtc()).isTrue(); - Assert.assertEquals(dateStr, bipDate.toString()); + assertThat(bipDate.toString()).isEqualTo(dateStr); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java index 2ffb5a9870..99f4a5281a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,10 +34,10 @@ public class BipEncodingTest { String propId, boolean isAndroidSupported) { BipEncoding encoding = new BipEncoding(input); - Assert.assertEquals(encodingType, encoding.getType()); - Assert.assertEquals(encodingStr, encoding.toString()); - Assert.assertEquals(propId, encoding.getProprietaryEncodingId()); - Assert.assertEquals(isAndroidSupported, encoding.isAndroidSupported()); + assertThat(encoding.getType()).isEqualTo(encodingType); + assertThat(encoding.toString()).isEqualTo(encodingStr); + assertThat(encoding.getProprietaryEncodingId()).isEqualTo(propId); + assertThat(encoding.isAndroidSupported()).isEqualTo(isAndroidSupported); } private void testParseMany( @@ -111,26 +110,26 @@ public class BipEncodingTest { }; for (int encodingType : inputs) { BipEncoding encoding = new BipEncoding(encodingType, null); - Assert.assertEquals(encodingType, encoding.getType()); - Assert.assertEquals(null, encoding.getProprietaryEncodingId()); + assertThat(encoding.getType()).isEqualTo(encodingType); + assertThat(encoding.getProprietaryEncodingId()).isNull(); } } @Test public void testCreateProprietaryEncoding() { BipEncoding encoding = new BipEncoding(BipEncoding.USR_XXX, "test-encoding"); - Assert.assertEquals(BipEncoding.USR_XXX, encoding.getType()); - Assert.assertEquals("TEST-ENCODING", encoding.getProprietaryEncodingId()); - Assert.assertEquals("USR-TEST-ENCODING", encoding.toString()); + assertThat(encoding.getType()).isEqualTo(BipEncoding.USR_XXX); + assertThat(encoding.getProprietaryEncodingId()).isEqualTo("TEST-ENCODING"); + assertThat(encoding.toString()).isEqualTo("USR-TEST-ENCODING"); assertThat(encoding.isAndroidSupported()).isFalse(); } @Test public void testCreateProprietaryEncoding_emptyId() { BipEncoding encoding = new BipEncoding(BipEncoding.USR_XXX, ""); - Assert.assertEquals(BipEncoding.USR_XXX, encoding.getType()); - Assert.assertEquals("", encoding.getProprietaryEncodingId()); - Assert.assertEquals("USR-", encoding.toString()); + assertThat(encoding.getType()).isEqualTo(BipEncoding.USR_XXX); + assertThat(encoding.getProprietaryEncodingId()).isEqualTo(""); + assertThat(encoding.toString()).isEqualTo("USR-"); assertThat(encoding.isAndroidSupported()).isFalse(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java index 971ec50064..58f89753cd 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java @@ -22,7 +22,6 @@ import android.annotation.SuppressLint; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -47,7 +46,7 @@ public class BipImageDescriptorTest { builder.setFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -65,7 +64,7 @@ public class BipImageDescriptorTest { builder.setFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -78,12 +77,12 @@ public class BipImageDescriptorTest { + "</image-descriptor>"; BipImageDescriptor.Builder builder = new BipImageDescriptor.Builder(); - builder.setPropietaryEncoding("NOKIA-1"); + builder.setProprietaryEncoding("NOKIA-1"); builder.setFixedDimensions(1280, 960); builder.setFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -96,12 +95,12 @@ public class BipImageDescriptorTest { + "</image-descriptor>"; BipImageDescriptor.Builder builder = new BipImageDescriptor.Builder(); - builder.setPropietaryEncoding("NOKIA-1"); + builder.setProprietaryEncoding("NOKIA-1"); builder.setFixedDimensions(1280, 960); builder.setTransformation(BipTransformation.STRETCH); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -114,12 +113,12 @@ public class BipImageDescriptorTest { + "</image-descriptor>"; BipImageDescriptor.Builder builder = new BipImageDescriptor.Builder(); - builder.setPropietaryEncoding("NOKIA-1"); + builder.setProprietaryEncoding("NOKIA-1"); builder.setFixedDimensions(1280, 960); builder.setTransformation(BipTransformation.CROP); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -132,12 +131,12 @@ public class BipImageDescriptorTest { + "</image-descriptor>"; BipImageDescriptor.Builder builder = new BipImageDescriptor.Builder(); - builder.setPropietaryEncoding("NOKIA-1"); + builder.setProprietaryEncoding("NOKIA-1"); builder.setFixedDimensions(1280, 960); builder.setTransformation(BipTransformation.FILL); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -150,13 +149,13 @@ public class BipImageDescriptorTest { + "</image-descriptor>"; BipImageDescriptor.Builder builder = new BipImageDescriptor.Builder(); - builder.setPropietaryEncoding("NOKIA-1"); + builder.setProprietaryEncoding("NOKIA-1"); builder.setFixedDimensions(1280, 960); builder.setTransformation(BipTransformation.CROP); builder.setTransformation(BipTransformation.FILL); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -172,7 +171,7 @@ public class BipImageDescriptorTest { builder.setFixedDimensions(1280, 960); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -189,7 +188,7 @@ public class BipImageDescriptorTest { builder.setMaxFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -208,7 +207,7 @@ public class BipImageDescriptorTest { builder.setTransformation(BipTransformation.FILL); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(expected, descriptor.toString()); + assertThat(descriptor.toString()).isEqualTo(expected); } @Test @@ -218,7 +217,7 @@ public class BipImageDescriptorTest { builder.setFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(null, descriptor.toString()); + assertThat(descriptor.toString()).isNull(); } @Test @@ -228,7 +227,7 @@ public class BipImageDescriptorTest { builder.setFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(null, descriptor.toString()); + assertThat(descriptor.toString()).isNull(); } @Test @@ -237,7 +236,7 @@ public class BipImageDescriptorTest { builder.setFileSize(500000); BipImageDescriptor descriptor = builder.build(); - Assert.assertEquals(null, descriptor.toString()); + assertThat(descriptor.toString()).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java index 9c8aec1b85..2f1e60cf34 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java @@ -22,7 +22,6 @@ import android.annotation.SuppressLint; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,52 +32,52 @@ public class BipImageFormatTest { public void testParseNative_requiredOnly() { String expected = "<native encoding=\"JPEG\" pixel=\"1280*1024\" />"; BipImageFormat format = BipImageFormat.parseNative("JPEG", "1280*1024", null); - Assert.assertEquals(BipImageFormat.FORMAT_NATIVE, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(new BipTransformation(), format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_NATIVE); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(new BipTransformation()); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test public void testParseNative_withSize() { String expected = "<native encoding=\"JPEG\" pixel=\"1280*1024\" size=\"1048576\" />"; BipImageFormat format = BipImageFormat.parseNative("JPEG", "1280*1024", "1048576"); - Assert.assertEquals(BipImageFormat.FORMAT_NATIVE, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(new BipTransformation(), format.getTransformation()); - Assert.assertEquals(1048576, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_NATIVE); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(new BipTransformation()); + assertThat(format.getSize()).isEqualTo(1048576); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test public void testParseVariant_requiredOnly() { String expected = "<variant encoding=\"JPEG\" pixel=\"1280*1024\" />"; BipImageFormat format = BipImageFormat.parseVariant("JPEG", "1280*1024", null, null); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(new BipTransformation(), format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(new BipTransformation()); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test public void testParseVariant_withMaxSize() { String expected = "<variant encoding=\"JPEG\" pixel=\"1280*1024\" maxsize=\"1048576\" />"; BipImageFormat format = BipImageFormat.parseVariant("JPEG", "1280*1024", "1048576", null); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(new BipTransformation(), format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(1048576, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(new BipTransformation()); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(1048576); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -93,16 +92,16 @@ public class BipImageFormatTest { BipImageFormat format = BipImageFormat.parseVariant("JPEG", "1280*1024", null, "stretch fill crop"); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.toString()).isEqualTo(expected); format = BipImageFormat.parseVariant("JPEG", "1280*1024", null, "stretch crop fill"); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.toString()).isEqualTo(expected); format = BipImageFormat.parseVariant("JPEG", "1280*1024", null, "crop stretch fill"); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -117,31 +116,31 @@ public class BipImageFormatTest { BipImageFormat format = BipImageFormat.parseVariant("JPEG", "1280*1024", "1048576", "stretch fill crop"); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(1048576, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(1048576); + assertThat(format.toString()).isEqualTo(expected); format = BipImageFormat.parseVariant("JPEG", "1280*1024", "1048576", "stretch crop fill"); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(1048576, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(1048576); + assertThat(format.toString()).isEqualTo(expected); format = BipImageFormat.parseVariant("JPEG", "1280*1024", "1048576", "crop stretch fill"); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(1048576, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(1048576); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -152,13 +151,13 @@ public class BipImageFormatTest { new BipEncoding(BipEncoding.JPEG, null), BipPixel.createFixed(1280, 1024), -1); - Assert.assertEquals(BipImageFormat.FORMAT_NATIVE, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(new BipTransformation(), format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_NATIVE); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isNull(); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -169,13 +168,13 @@ public class BipImageFormatTest { new BipEncoding(BipEncoding.JPEG, null), BipPixel.createFixed(1280, 1024), 1048576); - Assert.assertEquals(BipImageFormat.FORMAT_NATIVE, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(1280, 1024), format.getPixel()); - Assert.assertEquals(new BipTransformation(), format.getTransformation()); - Assert.assertEquals(1048576, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_NATIVE); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(1280, 1024)); + assertThat(format.getTransformation()).isNull(); + assertThat(format.getSize()).isEqualTo(1048576); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -187,13 +186,13 @@ public class BipImageFormatTest { BipPixel.createFixed(32, 32), -1, null); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(32, 32), format.getPixel()); - Assert.assertEquals(null, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(32, 32)); + assertThat(format.getTransformation()).isNull(); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -214,13 +213,13 @@ public class BipImageFormatTest { BipPixel.createFixed(32, 32), -1, trans); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(32, 32), format.getPixel()); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(-1, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(32, 32)); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(-1); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -232,13 +231,13 @@ public class BipImageFormatTest { BipPixel.createFixed(32, 32), 123, null); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(32, 32), format.getPixel()); - Assert.assertEquals(null, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(123, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(32, 32)); + assertThat(format.getTransformation()).isNull(); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(123); + assertThat(format.toString()).isEqualTo(expected); } @Test @@ -259,13 +258,13 @@ public class BipImageFormatTest { BipPixel.createFixed(32, 32), 123, trans); - Assert.assertEquals(BipImageFormat.FORMAT_VARIANT, format.getType()); - Assert.assertEquals(new BipEncoding(BipEncoding.JPEG, null), format.getEncoding()); - Assert.assertEquals(BipPixel.createFixed(32, 32), format.getPixel()); - Assert.assertEquals(trans, format.getTransformation()); - Assert.assertEquals(-1, format.getSize()); - Assert.assertEquals(123, format.getMaxSize()); - Assert.assertEquals(expected, format.toString()); + assertThat(format.getType()).isEqualTo(BipImageFormat.FORMAT_VARIANT); + assertThat(format.getEncoding()).isEqualTo(new BipEncoding(BipEncoding.JPEG, null)); + assertThat(format.getPixel()).isEqualTo(BipPixel.createFixed(32, 32)); + assertThat(format.getTransformation()).isEqualTo(trans); + assertThat(format.getSize()).isEqualTo(-1); + assertThat(format.getMaxSize()).isEqualTo(123); + assertThat(format.toString()).isEqualTo(expected); } @Test(expected = ParseException.class) diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java index c238f914d9..6e767249e9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -131,11 +130,11 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(null, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isNull(); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } /** @@ -166,11 +165,11 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } /** @@ -192,12 +191,12 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(null, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isNull(); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isFalse(); - Assert.assertEquals(xmlString, properties.toString()); - Assert.assertEquals(null, properties.serialize()); + assertThat(properties.toString()).isEqualTo(xmlString); + assertThat(properties.serialize()).isNull(); } /** @@ -219,12 +218,12 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(null, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isNull(); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isFalse(); - Assert.assertEquals(xmlString, properties.toString()); - Assert.assertEquals(null, properties.serialize()); + assertThat(properties.toString()).isEqualTo(xmlString); + assertThat(properties.serialize()).isNull(); } /** @@ -245,11 +244,11 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(null, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isNull(); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } /** @@ -268,11 +267,11 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } /** @@ -291,11 +290,11 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } /** @@ -314,11 +313,11 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } /** @@ -342,12 +341,12 @@ public class BipImagePropertiesTest { + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isFalse(); - Assert.assertEquals(xmlString, properties.toString()); - Assert.assertEquals(null, properties.serialize()); + assertThat(properties.toString()).isEqualTo(xmlString); + assertThat(properties.serialize()).isNull(); } /** @@ -361,11 +360,11 @@ public class BipImagePropertiesTest { String xmlString = XML_DOC_DECL + IMAGE_PROPERTIES + IMAGE_PROPERTIES_END; InputStream stream = toUtf8Stream(xmlString); BipImageProperties properties = new BipImageProperties(stream); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isFalse(); - Assert.assertEquals(null, properties.serialize()); + assertThat(properties.serialize()).isNull(); } /** Test parsing an image-properties with no open tag */ @@ -447,10 +446,10 @@ public class BipImagePropertiesTest { new BipAttachmentFormat("audio/basic", null, "ABCD1234.wav", 102400, null, null)); BipImageProperties properties = builder.build(); - Assert.assertEquals(IMAGE_HANDLE, properties.getImageHandle()); - Assert.assertEquals(VERSION, properties.getVersion()); - Assert.assertEquals(FRIENDLY_NAME, properties.getFriendlyName()); + assertThat(properties.getImageHandle()).isEqualTo(IMAGE_HANDLE); + assertThat(properties.getVersion()).isEqualTo(VERSION); + assertThat(properties.getFriendlyName()).isEqualTo(FRIENDLY_NAME); assertThat(properties.isValid()).isTrue(); - Assert.assertEquals(xmlString, properties.toString()); + assertThat(properties.toString()).isEqualTo(xmlString); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java index 87ffdc5387..e3ee39dee5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java @@ -27,7 +27,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,7 +55,7 @@ public class BipImageTest { mTestResources.openRawResource(com.android.bluetooth.tests.R.raw.image_200_200); Bitmap bitmap = BitmapFactory.decodeStream(expectedInputStream); - Assert.assertEquals(sImageHandle, image.getImageHandle()); + assertThat(image.getImageHandle()).isEqualTo(sImageHandle); assertThat(bitmap.sameAs(image.getImage())).isTrue(); } @@ -70,7 +69,7 @@ public class BipImageTest { mTestResources.openRawResource(com.android.bluetooth.tests.R.raw.image_600_600); Bitmap bitmap = BitmapFactory.decodeStream(expectedInputStream); - Assert.assertEquals(sImageHandle, image.getImageHandle()); + assertThat(image.getImageHandle()).isEqualTo(sImageHandle); assertThat(bitmap.sameAs(image.getImage())).isTrue(); } @@ -80,7 +79,7 @@ public class BipImageTest { mTestResources.openRawResource(com.android.bluetooth.tests.R.raw.image_200_200); Bitmap bitmap = BitmapFactory.decodeStream(imageInputStream); BipImage image = new BipImage(sImageHandle, bitmap); - Assert.assertEquals(sImageHandle, image.getImageHandle()); + assertThat(image.getImageHandle()).isEqualTo(sImageHandle); assertThat(bitmap.sameAs(image.getImage())).isTrue(); } @@ -90,7 +89,7 @@ public class BipImageTest { mTestResources.openRawResource(com.android.bluetooth.tests.R.raw.image_600_600); Bitmap bitmap = BitmapFactory.decodeStream(imageInputStream); BipImage image = new BipImage(sImageHandle, bitmap); - Assert.assertEquals(sImageHandle, image.getImageHandle()); + assertThat(image.getImageHandle()).isEqualTo(sImageHandle); assertThat(bitmap.sameAs(image.getImage())).isTrue(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java index e40ef9cefc..88f093966a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java @@ -16,9 +16,10 @@ package com.android.bluetooth.avrcpcontroller; +import static com.google.common.truth.Truth.assertThat; + import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,44 +36,44 @@ public class BipPixelTest { int maxHeight, String pixelStr) { BipPixel pixel = new BipPixel(input); - Assert.assertEquals(pixelType, pixel.getType()); - Assert.assertEquals(minWidth, pixel.getMinWidth()); - Assert.assertEquals(minHeight, pixel.getMinHeight()); - Assert.assertEquals(maxWidth, pixel.getMaxWidth()); - Assert.assertEquals(maxHeight, pixel.getMaxHeight()); - Assert.assertEquals(pixelStr, pixel.toString()); + assertThat(pixel.getType()).isEqualTo(pixelType); + assertThat(pixel.getMinWidth()).isEqualTo(minWidth); + assertThat(pixel.getMinHeight()).isEqualTo(minHeight); + assertThat(pixel.getMaxWidth()).isEqualTo(maxWidth); + assertThat(pixel.getMaxHeight()).isEqualTo(maxHeight); + assertThat(pixel.toString()).isEqualTo(pixelStr); } private void testFixed(int width, int height, String pixelStr) { BipPixel pixel = BipPixel.createFixed(width, height); - Assert.assertEquals(BipPixel.TYPE_FIXED, pixel.getType()); - Assert.assertEquals(width, pixel.getMinWidth()); - Assert.assertEquals(height, pixel.getMinHeight()); - Assert.assertEquals(width, pixel.getMaxWidth()); - Assert.assertEquals(height, pixel.getMaxHeight()); - Assert.assertEquals(pixelStr, pixel.toString()); + assertThat(pixel.getType()).isEqualTo(BipPixel.TYPE_FIXED); + assertThat(pixel.getMinWidth()).isEqualTo(width); + assertThat(pixel.getMinHeight()).isEqualTo(height); + assertThat(pixel.getMaxWidth()).isEqualTo(width); + assertThat(pixel.getMaxHeight()).isEqualTo(height); + assertThat(pixel.toString()).isEqualTo(pixelStr); } private void testResizableModified( int minWidth, int minHeight, int maxWidth, int maxHeight, String pixelStr) { BipPixel pixel = BipPixel.createResizableModified(minWidth, minHeight, maxWidth, maxHeight); - Assert.assertEquals(BipPixel.TYPE_RESIZE_MODIFIED_ASPECT_RATIO, pixel.getType()); - Assert.assertEquals(minWidth, pixel.getMinWidth()); - Assert.assertEquals(minHeight, pixel.getMinHeight()); - Assert.assertEquals(maxWidth, pixel.getMaxWidth()); - Assert.assertEquals(maxHeight, pixel.getMaxHeight()); - Assert.assertEquals(pixelStr, pixel.toString()); + assertThat(pixel.getType()).isEqualTo(BipPixel.TYPE_RESIZE_MODIFIED_ASPECT_RATIO); + assertThat(pixel.getMinWidth()).isEqualTo(minWidth); + assertThat(pixel.getMinHeight()).isEqualTo(minHeight); + assertThat(pixel.getMaxWidth()).isEqualTo(maxWidth); + assertThat(pixel.getMaxHeight()).isEqualTo(maxHeight); + assertThat(pixel.toString()).isEqualTo(pixelStr); } private void testResizableFixed(int minWidth, int maxWidth, int maxHeight, String pixelStr) { int minHeight = (minWidth * maxHeight) / maxWidth; // spec defined BipPixel pixel = BipPixel.createResizableFixed(minWidth, maxWidth, maxHeight); - Assert.assertEquals(BipPixel.TYPE_RESIZE_FIXED_ASPECT_RATIO, pixel.getType()); - Assert.assertEquals(minWidth, pixel.getMinWidth()); - Assert.assertEquals(minHeight, pixel.getMinHeight()); - Assert.assertEquals(maxWidth, pixel.getMaxWidth()); - Assert.assertEquals(maxHeight, pixel.getMaxHeight()); - Assert.assertEquals(pixelStr, pixel.toString()); + assertThat(pixel.getType()).isEqualTo(BipPixel.TYPE_RESIZE_FIXED_ASPECT_RATIO); + assertThat(pixel.getMinWidth()).isEqualTo(minWidth); + assertThat(pixel.getMinHeight()).isEqualTo(minHeight); + assertThat(pixel.getMaxWidth()).isEqualTo(maxWidth); + assertThat(pixel.getMaxHeight()).isEqualTo(maxHeight); + assertThat(pixel.toString()).isEqualTo(pixelStr); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java index 3b5893c1f1..031a71c81e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java @@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,7 +31,7 @@ public class BipTransformationTest { public void testCreateEmpty() { BipTransformation trans = new BipTransformation(); assertThat(trans.supportsAny()).isFalse(); - Assert.assertEquals(null, trans.toString()); + assertThat(trans.toString()).isNull(); } @Test @@ -42,13 +41,13 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); trans.addTransformation(BipTransformation.STRETCH); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("stretch crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch crop"); } @Test @@ -58,13 +57,13 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); trans.addTransformation(BipTransformation.CROP); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); } @Test(expected = IllegalArgumentException.class) @@ -87,14 +86,14 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); trans.removeTransformation(BipTransformation.CROP); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.supportsAny()).isFalse(); - Assert.assertEquals(null, trans.toString()); + assertThat(trans.toString()).isNull(); } @Test @@ -105,13 +104,13 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("stretch crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch crop"); trans.removeTransformation(BipTransformation.CROP); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("stretch", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch"); } @Test(expected = IllegalArgumentException.class) @@ -123,7 +122,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("stretch crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch crop"); } @Test @@ -135,7 +134,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("stretch crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch crop"); } @Test @@ -144,7 +143,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("stretch", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch"); } @Test @@ -153,7 +152,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); } @Test @@ -162,7 +161,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("fill", trans.toString()); + assertThat(trans.toString()).isEqualTo("fill"); } @Test @@ -171,7 +170,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("stretch fill", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill"); } @Test @@ -180,7 +179,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); - Assert.assertEquals("stretch crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch crop"); } @Test @@ -189,7 +188,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); - Assert.assertEquals("fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("fill crop"); } @Test @@ -198,7 +197,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("stretch fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill crop"); } @Test @@ -207,7 +206,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); - Assert.assertEquals("fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("fill crop"); } @Test @@ -216,7 +215,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("stretch fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill crop"); } @Test @@ -225,7 +224,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("stretch fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill crop"); } @Test @@ -234,7 +233,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("stretch", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch"); } @Test @@ -243,7 +242,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("fill", trans.toString()); + assertThat(trans.toString()).isEqualTo("fill"); } @Test @@ -252,7 +251,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); } @Test @@ -261,7 +260,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("crop"); } @Test @@ -272,7 +271,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("stretch fill", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill"); } @Test @@ -287,7 +286,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("stretch fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill crop"); } @Test @@ -302,7 +301,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("stretch fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill crop"); } @Test(expected = IllegalArgumentException.class) @@ -321,7 +320,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals(null, trans.toString()); + assertThat(trans.toString()).isNull(); } @Test @@ -330,7 +329,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("stretch fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch fill crop"); } @Test @@ -339,7 +338,7 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isFalse(); assertThat(trans.isSupported(BipTransformation.FILL)).isTrue(); assertThat(trans.isSupported(BipTransformation.CROP)).isTrue(); - Assert.assertEquals("fill crop", trans.toString()); + assertThat(trans.toString()).isEqualTo("fill crop"); } @Test @@ -348,6 +347,6 @@ public class BipTransformationTest { assertThat(trans.isSupported(BipTransformation.STRETCH)).isTrue(); assertThat(trans.isSupported(BipTransformation.FILL)).isFalse(); assertThat(trans.isSupported(BipTransformation.CROP)).isFalse(); - Assert.assertEquals("stretch", trans.toString()); + assertThat(trans.toString()).isEqualTo("stretch"); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java index 93082e863a..1e83cdeab3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java @@ -142,8 +142,7 @@ public class BaseDataTest { (byte) 'A', // codecConfigInfo }; - BaseData data = BaseData.parseBaseData(serviceData); - assertThat(data).isEqualTo(null); + assertThat(BaseData.parseBaseData(serviceData)).isNull(); } @Test @@ -173,8 +172,7 @@ public class BaseDataTest { (byte) 0x08, // metaData }; - BaseData data = BaseData.parseBaseData(serviceData); - assertThat(data).isEqualTo(null); + assertThat(BaseData.parseBaseData(serviceData)).isNull(); } @Test @@ -210,8 +208,7 @@ public class BaseDataTest { (byte) 'C' // codecConfigInfo }; - BaseData data = BaseData.parseBaseData(serviceData); - assertThat(data).isEqualTo(null); + assertThat(BaseData.parseBaseData(serviceData)).isNull(); } @Test @@ -392,8 +389,7 @@ public class BaseDataTest { (byte) 0x00, // metaDataLength }; - BaseData data = BaseData.parseBaseData(serviceData); - assertThat(data).isEqualTo(null); + assertThat(BaseData.parseBaseData(serviceData)).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 0796f48a7a..f382387f42 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -86,7 +86,6 @@ import com.android.bluetooth.le_audio.LeAudioService; import com.google.common.truth.Expect; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -291,6 +290,7 @@ public class BassClientServiceTest { doReturn((BluetoothDevice) invocation.getArgument(0)) .when(stateMachine) .getDevice(); + doReturn(true).when(stateMachine).isBassStateReady(); mStateMachines.put( (BluetoothDevice) invocation.getArgument(0), stateMachine); return stateMachine; @@ -396,10 +396,8 @@ public class BassClientServiceTest { when(mDatabaseManager.getProfileConnectionPolicy( mCurrentDevice, BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - Assert.assertEquals( - "Initial device policy", - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mBassClientService.getConnectionPolicy(mCurrentDevice)); + assertThat(mBassClientService.getConnectionPolicy(mCurrentDevice)) + .isEqualTo(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); } /** @@ -617,7 +615,7 @@ public class BassClientServiceTest { .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); expect.that(mBassClientService.getActiveSyncedSources()).isEmpty(); - expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isNull(); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); } @@ -651,7 +649,7 @@ public class BassClientServiceTest { .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); expect.that(mBassClientService.getActiveSyncedSources()).isEmpty(); - expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isNull(); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); } @@ -987,7 +985,7 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - // Error in syncEstablished causes soureLost, sourceAddFailed notification + // Error in syncEstablished causes sourceLost, sourceAddFailed notification // and removing cache because scanning is active onSyncEstablishedFailed(device1, handle1); TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); @@ -1042,7 +1040,7 @@ public class BassClientServiceTest { .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - // Error in syncEstablished causes soureLost, sourceAddFailed notification + // Error in syncEstablished causes sourceLost, sourceAddFailed notification // and not removing cache because scanning is inactice onSyncEstablishedFailed(device1, handle1); TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); @@ -1159,7 +1157,7 @@ public class BassClientServiceTest { mBassClientService.addSource(mCurrentDevice1, meta, false); handleHandoverSupport(); - // Error in syncEstablished causes soureLost, sourceAddFailed notification for both sinks + // Error in syncEstablished causes sourceLost, sourceAddFailed notification for both sinks onSyncEstablishedFailed(mSourceDevice, TEST_SYNC_HANDLE); TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); InOrder inOrderCallback = inOrder(mCallback); @@ -2044,7 +2042,7 @@ public class BassClientServiceTest { assertThat(msg.get().arg1).isEqualTo(TEST_SOURCE_ID); assertThat(msg.get().arg2).isEqualTo(BassConstants.PA_SYNC_DO_NOT_SYNC); // Verify metadata is null - assertThat(msg.get().obj).isEqualTo(null); + assertThat(msg.get().obj).isNull(); } for (BassClientStateMachine sm : mStateMachines.values()) { @@ -2073,7 +2071,7 @@ public class BassClientServiceTest { null); doReturn(null).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID)); assertThat(mBassClientService.getSourceMetadata(sm.getDevice(), TEST_SOURCE_ID)) - .isEqualTo(null); + .isNull(); doReturn(meta).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID)); doReturn(true).when(sm).isSyncedToTheSource(eq(TEST_SOURCE_ID)); @@ -2534,8 +2532,8 @@ public class BassClientServiceTest { prepareConnectedDeviceGroup(); assertThat(mStateMachines.size()).isEqualTo(2); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isEqualTo(null); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isEqualTo(null); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNull(); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNull(); // Verify add active synced source mBassClientService.addActiveSyncedSource(mCurrentDevice, testSyncHandle); @@ -2543,10 +2541,8 @@ public class BassClientServiceTest { // Verify duplicated source won't be added mBassClientService.addActiveSyncedSource(mCurrentDevice, testSyncHandle); mBassClientService.addActiveSyncedSource(mCurrentDevice1, testSyncHandle); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)) - .isNotEqualTo(null); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)) - .isNotEqualTo(null); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNotNull(); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNotNull(); assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice).size()) .isEqualTo(1); assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1).size()) @@ -2555,8 +2551,8 @@ public class BassClientServiceTest { // Verify remove active synced source mBassClientService.removeActiveSyncedSource(mCurrentDevice, testSyncHandle); mBassClientService.removeActiveSyncedSource(mCurrentDevice1, testSyncHandle); - expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isEqualTo(null); - expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isEqualTo(null); + expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNull(); + expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNull(); } } @@ -2833,7 +2829,7 @@ public class BassClientServiceTest { 0x56, 0x18, 0x07, - 0x04, // WRONG PUBLIC_BROADCAST data (metada size) + 0x04, // WRONG PUBLIC_BROADCAST data (metadata size) 0x06, 0x07, 0x08, @@ -2913,11 +2909,11 @@ public class BassClientServiceTest { // Two SyncRequest queued but not synced yet assertThat(mBassClientService.getActiveSyncedSources()).isEmpty(); - assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)) @@ -2938,10 +2934,10 @@ public class BassClientServiceTest { assertThat(mBassClientService.getActiveSyncedSources().size()).isEqualTo(1); assertThat(mBassClientService.getActiveSyncedSources()).containsExactly(handle1); assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(device1); - assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)).isEqualTo(broadcastId1); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); @@ -2960,9 +2956,9 @@ public class BassClientServiceTest { .inOrder(); assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(device1); assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); - assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)).isEqualTo(broadcastId1); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)).isEqualTo(broadcastId2); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle3)) @@ -2985,8 +2981,8 @@ public class BassClientServiceTest { .inOrder(); assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); - assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(null); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isNull(); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)).isEqualTo(broadcastId1); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)).isEqualTo(broadcastId2); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle3)).isEqualTo(broadcastId3); @@ -3010,7 +3006,7 @@ public class BassClientServiceTest { assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)).isEqualTo(broadcastId1); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)).isEqualTo(broadcastId2); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle3)).isEqualTo(broadcastId3); @@ -3031,11 +3027,11 @@ public class BassClientServiceTest { assertThat(mBassClientService.getActiveSyncedSources()) .containsExactly(handle2, handle3, handle4) .inOrder(); - assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isNull(); assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)).isEqualTo(broadcastId2); @@ -3050,7 +3046,7 @@ public class BassClientServiceTest { expect.that(mBassClientService.getActiveSyncedSources()) .containsExactly(handle2, handle3, handle4, handle5) .inOrder(); - expect.that(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(handle1)).isNull(); expect.that(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); expect.that(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); expect.that(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); @@ -3119,7 +3115,7 @@ public class BassClientServiceTest { assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)).isEqualTo(broadcastId1); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)).isEqualTo(broadcastId2); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle3)).isEqualTo(broadcastId3); @@ -3146,10 +3142,10 @@ public class BassClientServiceTest { .containsExactly(handle1, handle3, handle4) .inOrder(); expect.that(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(device1); - expect.that(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(handle2)).isNull(); expect.that(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); expect.that(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); - expect.that(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); expect.that(mBassClientService.getBroadcastIdForSyncHandle(handle1)) .isEqualTo(broadcastId1); expect.that(mBassClientService.getBroadcastIdForSyncHandle(handle2)) @@ -3214,7 +3210,7 @@ public class BassClientServiceTest { assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); - assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle1)).isEqualTo(broadcastId1); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle2)).isEqualTo(broadcastId2); assertThat(mBassClientService.getBroadcastIdForSyncHandle(handle3)).isEqualTo(broadcastId3); @@ -3279,11 +3275,11 @@ public class BassClientServiceTest { expect.that(mBassClientService.getActiveSyncedSources()) .containsExactly(handle2, handle3, handle4) .inOrder(); - expect.that(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(handle1)).isNull(); expect.that(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); expect.that(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); expect.that(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); - expect.that(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(handle5)).isNull(); expect.that(mBassClientService.getBroadcastIdForSyncHandle(handle1)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); expect.that(mBassClientService.getBroadcastIdForSyncHandle(handle2)) @@ -3354,7 +3350,7 @@ public class BassClientServiceTest { assertThat(mBassClientService.getActiveSyncedSources()) .containsExactly(handle2, handle3, handle4, handle5) .inOrder(); - assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(handle1)).isNull(); assertThat(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(device2); assertThat(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); assertThat(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); @@ -3410,7 +3406,7 @@ public class BassClientServiceTest { .containsExactly(handle3, handle4, handle5, handle1) .inOrder(); expect.that(mBassClientService.getDeviceForSyncHandle(handle1)).isEqualTo(device1); - expect.that(mBassClientService.getDeviceForSyncHandle(handle2)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(handle2)).isNull(); expect.that(mBassClientService.getDeviceForSyncHandle(handle3)).isEqualTo(device3); expect.that(mBassClientService.getDeviceForSyncHandle(handle4)).isEqualTo(device4); expect.that(mBassClientService.getDeviceForSyncHandle(handle5)).isEqualTo(device5); @@ -3642,7 +3638,7 @@ public class BassClientServiceTest { prepareConnectedDeviceGroup(); startSearchingForSources(); - // Added and executed immidiatelly as no other in queue + // Added and executed immediately as no other in queue mCallbackCaptor .getValue() .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); @@ -3840,7 +3836,7 @@ public class BassClientServiceTest { // Test using onSyncEstablishedFailed - // Added and executed immidiatelly as no other in queue, high rssi + // Added and executed immediately as no other in queue, high rssi mCallbackCaptor .getValue() .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); @@ -3923,7 +3919,7 @@ public class BassClientServiceTest { // Test using onSyncLost - // Added and executed immidiatelly as no other in queue, high rssi + // Added and executed immediately as no other in queue, high rssi mCallbackCaptor .getValue() .onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult1); @@ -4000,8 +3996,8 @@ public class BassClientServiceTest { // Verify add active synced source mBassClientService.addActiveSyncedSource(mCurrentDevice, testSyncHandle); mBassClientService.addActiveSyncedSource(mCurrentDevice1, testSyncHandle); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNotEqualTo(null); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNotEqualTo(null); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNotNull(); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNotNull(); assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice).size()).isEqualTo(1); assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1).size()).isEqualTo(1); @@ -4013,8 +4009,8 @@ public class BassClientServiceTest { mBassClientService.addActiveSyncedSource(mCurrentDevice, testSyncHandle3); mBassClientService.addActiveSyncedSource(mCurrentDevice1, testSyncHandle3); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNotEqualTo(null); - assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNotEqualTo(null); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNotNull(); + assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNotNull(); assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice).size()).isEqualTo(4); assertThat(mBassClientService.getActiveSyncedSources(mCurrentDevice1).size()).isEqualTo(4); @@ -4038,8 +4034,8 @@ public class BassClientServiceTest { // Verify remove all active synced source mBassClientService.removeActiveSyncedSource(mCurrentDevice, null); mBassClientService.removeActiveSyncedSource(mCurrentDevice1, null); - expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isEqualTo(null); - expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isEqualTo(null); + expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice)).isNull(); + expect.that(mBassClientService.getActiveSyncedSources(mCurrentDevice1)).isNull(); } @Test @@ -4078,7 +4074,7 @@ public class BassClientServiceTest { assertThat( mBassClientService.getPeriodicAdvertisementResult( mSourceDevice, testBroadcastIdInvalid)) - .isEqualTo(null); + .isNull(); PeriodicAdvertisementResult paResult = mBassClientService.getPeriodicAdvertisementResult(mSourceDevice, testBroadcastId); assertThat(paResult.getAddressType()).isEqualTo(BluetoothDevice.ADDRESS_TYPE_RANDOM); @@ -4134,7 +4130,7 @@ public class BassClientServiceTest { assertThat( mBassClientService.getPeriodicAdvertisementResult( mSourceDevice, testBroadcastId2)) - .isEqualTo(null); + .isNull(); PeriodicAdvertisementResult paResult = mBassClientService.getPeriodicAdvertisementResult(mSourceDevice, testBroadcastId1); assertThat(paResult.getAddressType()).isEqualTo(BluetoothDevice.ADDRESS_TYPE_RANDOM); @@ -4170,7 +4166,7 @@ public class BassClientServiceTest { expect.that( mBassClientService.getPeriodicAdvertisementResult( mSourceDevice, testBroadcastId1)) - .isEqualTo(null); + .isNull(); paResult = mBassClientService.getPeriodicAdvertisementResult(mSourceDevice, testBroadcastId2); expect.that(paResult.getAddressType()).isEqualTo(BluetoothDevice.ADDRESS_TYPE_RANDOM); @@ -4441,27 +4437,36 @@ public class BassClientServiceTest { } @Test - public void testIsAnyReceiverReceivingBroadcast() { + public void testIsAnyReceiverActive() { prepareConnectedDeviceGroup(); startSearchingForSources(); onScanResult(mSourceDevice, TEST_BROADCAST_ID); onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); verifyAddSourceForGroup(meta); - prepareRemoteSourceState(meta, true, false); + prepareRemoteSourceState(meta, false, false); List<BluetoothDevice> devices = mBassClientService.getConnectedDevices(); - // Verify isAnyReceiverReceivingBroadcast returns false if no BIS synced - assertThat(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isFalse(); + // Verify isAnyReceiverActive returns false if no PA and no BIS synced + assertThat(mBassClientService.isAnyReceiverActive(devices)).isFalse(); - // Update receiver state with BIS sync - injectRemoteSourceStateChanged(meta, true, true); + // Update receiver state with PA sync + injectRemoteSourceStateChanged(meta, true, false); BluetoothDevice invalidDevice = TestUtils.getTestDevice(mBluetoothAdapter, 2); - // Verify isAnyReceiverReceivingBroadcast returns false if invalid device - expect.that(mBassClientService.isAnyReceiverReceivingBroadcast(List.of(invalidDevice))) - .isFalse(); - // Verify isAnyReceiverReceivingBroadcast returns true if BIS synced - expect.that(mBassClientService.isAnyReceiverReceivingBroadcast(devices)).isTrue(); + // Verify isAnyReceiverActive returns false if invalid device + expect.that(mBassClientService.isAnyReceiverActive(List.of(invalidDevice))).isFalse(); + // Verify isAnyReceiverActive returns true if PA synced + expect.that(mBassClientService.isAnyReceiverActive(devices)).isTrue(); + + // Update receiver state with PA and BIS sync + injectRemoteSourceStateChanged(meta, true, true); + // Verify isAnyReceiverActive returns true if PA and BIS synced + expect.that(mBassClientService.isAnyReceiverActive(devices)).isTrue(); + + // Update receiver state with BIS only sync + injectRemoteSourceStateChanged(meta, false, true); + // Verify isAnyReceiverActive returns true if BIS only synced + expect.that(mBassClientService.isAnyReceiverActive(devices)).isTrue(); } @Test @@ -4811,7 +4816,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); byte[] scanRecord = new byte[] { @@ -4867,7 +4872,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -4876,10 +4881,10 @@ public class BassClientServiceTest { // Canceled, not updated base expect.that(mBassClientService.getActiveSyncedSources()).isEmpty(); - expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isNull(); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); - expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -4902,7 +4907,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); byte[] scanRecord = new byte[] { @@ -4967,7 +4972,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -4976,10 +4981,10 @@ public class BassClientServiceTest { // Canceled, not updated base expect.that(mBassClientService.getActiveSyncedSources()).isEmpty(); - expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + expect.that(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isNull(); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); - expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); mInOrderMethodProxy .verify(mMethodProxy) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -5002,7 +5007,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); onPeriodicAdvertisingReport(); @@ -5013,7 +5018,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null); + expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotNull(); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -5036,7 +5041,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); byte[] scanRecordNoBaseData = new byte[] { @@ -5143,7 +5148,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -5157,7 +5162,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null); + expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotNull(); mInOrderMethodProxy .verify(mMethodProxy, never()) .periodicAdvertisingManagerUnregisterSync(any(), any()); @@ -5176,7 +5181,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); onPeriodicAdvertisingReport(); @@ -5187,7 +5192,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotNull(); if (!Flags.leaudioBigDependsOnAudioState()) { onBigInfoAdvertisingReport(); @@ -5203,7 +5208,7 @@ public class BassClientServiceTest { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - Assert.assertEquals(TEST_RSSI, metaData.getValue().getRssi()); + assertThat(metaData.getValue().getRssi()).isEqualTo(TEST_RSSI); // Any of them should not notified second time onPeriodicAdvertisingReport(); @@ -5291,7 +5296,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); // No public announcement so it will not notify onPeriodicAdvertisingReport(); @@ -5303,7 +5308,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotNull(); // Not notified TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); @@ -5339,7 +5344,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); // Big report before periodic so before base update onBigInfoAdvertisingReport(); @@ -5362,7 +5367,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotNull(); if (!Flags.leaudioBigDependsOnAudioState()) { // onBigInfoAdvertisingReport causes notification @@ -5394,7 +5399,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNull(); byte[] scanRecordNoBaseData = new byte[] { @@ -5460,7 +5465,7 @@ public class BassClientServiceTest { .isEqualTo(mSourceDevice); expect.that(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(TEST_BROADCAST_ID); - expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotEqualTo(null); + expect.that(mBassClientService.getBase(TEST_SYNC_HANDLE)).isNotNull(); // Notified TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); @@ -5569,7 +5574,7 @@ public class BassClientServiceTest { // Cleaned all assertThat(mBassClientService.getActiveSyncedSources()).isEmpty(); - assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); @@ -5614,7 +5619,7 @@ public class BassClientServiceTest { // Cleaned all assertThat(mBassClientService.getActiveSyncedSources()).isEmpty(); - assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isEqualTo(null); + assertThat(mBassClientService.getDeviceForSyncHandle(TEST_SYNC_HANDLE)).isNull(); assertThat(mBassClientService.getBroadcastIdForSyncHandle(TEST_SYNC_HANDLE)) .isEqualTo(BassConstants.INVALID_BROADCAST_ID); @@ -6867,6 +6872,83 @@ public class BassClientServiceTest { } } + /** Test add pending source when BASS state get ready */ + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_RESYNC_HELPER, + Flags.FLAG_LEAUDIO_BROADCAST_EXTRACT_PERIODIC_SCANNER_FROM_STATE_MACHINE + }) + public void sinkBassStateReady_addPendingSource() { + prepareConnectedDeviceGroup(); + BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID); + // Verify adding source when Bass state not ready + for (BassClientStateMachine sm : mStateMachines.values()) { + doReturn(false).when(sm).isBassStateReady(); + } + doReturn(true).when(mLeAudioService).isPlaying(TEST_BROADCAST_ID); + doReturn(new ArrayList<BluetoothLeBroadcastMetadata>(Arrays.asList(meta))) + .when(mLeAudioService) + .getAllBroadcastMetadata(); + // Add broadcast source and got queued due to BASS not ready + mBassClientService.addSource(mCurrentDevice, meta, false); + + mBassClientService.getCallbacks().notifyBassStateSetupFailed(mCurrentDevice); + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + + // Verify adding source callback is triggered if BASS state initiate failed + try { + verify(mCallback, timeout(TIMEOUT_MS).atLeastOnce()) + .onSourceAddFailed( + eq(mCurrentDevice), + eq(meta), + eq(BluetoothStatusCodes.ERROR_REMOTE_NOT_ENOUGH_RESOURCES)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + // Verify not getting ADD_BCAST_SOURCE message if no pending source to add + for (BassClientStateMachine sm : mStateMachines.values()) { + doReturn(true).when(sm).isBassStateReady(); + } + mBassClientService.getCallbacks().notifyBassStateReady(mCurrentDevice); + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + + for (BassClientStateMachine sm : mStateMachines.values()) { + if (sm.getDevice().equals(mCurrentDevice)) { + verify(sm, never()).sendMessage(any()); + clearInvocations(sm); + } + } + + for (BassClientStateMachine sm : mStateMachines.values()) { + doReturn(false).when(sm).isBassStateReady(); + } + // Add broadcast source and got queued due to BASS not ready + mBassClientService.addSource(mCurrentDevice, meta, false); + + for (BassClientStateMachine sm : mStateMachines.values()) { + doReturn(true).when(sm).isBassStateReady(); + } + mBassClientService.getCallbacks().notifyBassStateReady(mCurrentDevice); + TestUtils.waitForLooperToFinishScheduledTask(mBassClientService.getCallbacks().getLooper()); + + // Verify adding source is resumed once BASS state ready + for (BassClientStateMachine sm : mStateMachines.values()) { + if (sm.getDevice().equals(mCurrentDevice)) { + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); + + Message msg = + messageCaptor.getAllValues().stream() + .filter(m -> (m.what == BassClientStateMachine.ADD_BCAST_SOURCE)) + .findFirst() + .orElse(null); + assertThat(msg).isNotNull(); + clearInvocations(sm); + } + } + } + @Test public void testIsLocalBroadacst() { int broadcastId = 12345; @@ -7011,7 +7093,7 @@ public class BassClientServiceTest { mBassClientService.syncRequestForPast( mCurrentDevice1, TEST_BROADCAST_ID, TEST_SOURCE_ID + 1); - // Sync will send INITIATE_PA_SYNC_TRANSFER and remove pending soure to add + // Sync will send INITIATE_PA_SYNC_TRANSFER and remove pending source to add onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE); verifyInitiatePaSyncTransferAndNoOthers(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index 919326767f..c2d0f41ccb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -110,7 +110,6 @@ import com.google.common.primitives.Bytes; import org.hamcrest.Matcher; import org.hamcrest.core.AllOf; -import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -145,8 +144,11 @@ public class BassClientStateMachineTest { private static final int WAIT_MS = 1_200; private static final int TEST_BROADCAST_ID = 42; private static final int TEST_SOURCE_ID = 1; + private static final int TEST_CHANNEL_INDEX = 1; private static final String TEST_BROADCAST_NAME = "Test"; private static final String EMPTY_BLUETOOTH_DEVICE_ADDRESS = "00:00:00:00:00:00"; + private static final byte OPCODE_UPDATE_SOURCE = 0x03; + private static final int UPDATE_SOURCE_FIXED_LENGTH = 6; private Context mTargetContext; private BluetoothAdapter mAdapter; private HandlerThread mHandlerThread; @@ -228,8 +230,8 @@ public class BassClientStateMachineTest { /** Test that default state is disconnected */ @Test public void testDefaultDisconnectedState() { - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mBassClientStateMachine.getConnectionState()); + assertThat(mBassClientStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); } /** @@ -259,9 +261,8 @@ public class BassClientStateMachineTest { .sendBroadcast(any(Intent.class), anyString()); // Check that we are in Disconnected state - Assert.assertThat( - mBassClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BassClientStateMachine.Disconnected.class)); + assertThat(mBassClientStateMachine.getCurrentState()) + .isInstanceOf(BassClientStateMachine.Disconnected.class); } @Test @@ -277,9 +278,8 @@ public class BassClientStateMachineTest { .sendBroadcast(any(Intent.class), anyString()); // Check that we are in Disconnected state - Assert.assertThat( - mBassClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BassClientStateMachine.Disconnected.class)); + assertThat(mBassClientStateMachine.getCurrentState()) + .isInstanceOf(BassClientStateMachine.Disconnected.class); assertThat(mBassClientStateMachine.mBluetoothGatt).isNull(); } @@ -298,13 +298,11 @@ public class BassClientStateMachineTest { intentArgument1.capture(), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mBassClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BassClientStateMachine.Connecting.class)); + assertThat(mBassClientStateMachine.getCurrentState()) + .isInstanceOf(BassClientStateMachine.Connecting.class); assertThat(mBassClientStateMachine.mGattCallback).isNotNull(); mBassClientStateMachine.notifyConnectionStateChanged( @@ -319,9 +317,8 @@ public class BassClientStateMachineTest { any(String[].class), any(BroadcastOptions.class)); - Assert.assertThat( - mBassClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BassClientStateMachine.Connected.class)); + assertThat(mBassClientStateMachine.getCurrentState()) + .isInstanceOf(BassClientStateMachine.Connected.class); } @Test @@ -339,13 +336,11 @@ public class BassClientStateMachineTest { intentArgument1.capture(), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mBassClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BassClientStateMachine.Connecting.class)); + assertThat(mBassClientStateMachine.getCurrentState()) + .isInstanceOf(BassClientStateMachine.Connecting.class); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); @@ -354,13 +349,11 @@ public class BassClientStateMachineTest { intentArgument2.capture(), any(String[].class), any(BroadcastOptions.class)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); - Assert.assertThat( - mBassClientStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(BassClientStateMachine.Disconnected.class)); + assertThat(mBassClientStateMachine.getCurrentState()) + .isInstanceOf(BassClientStateMachine.Disconnected.class); } @Test @@ -734,6 +727,8 @@ public class BassClientStateMachineTest { BassClientStateMachine.BluetoothGattTestableWrapper btGatt = Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); mBassClientStateMachine.mBluetoothGatt = btGatt; + BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); + when(mBassClientService.getCallbacks()).thenReturn(callbacks); // Do nothing if mDiscoveryInitiated is false. mBassClientStateMachine.mDiscoveryInitiated = false; @@ -748,6 +743,8 @@ public class BassClientStateMachineTest { cb.onServicesDiscovered(null, status); verify(btGatt, never()).requestMtu(anyInt()); + verify(callbacks).notifyBassStateSetupFailed(eq(mBassClientStateMachine.getDevice())); + assertThat(mBassClientStateMachine.isBassStateReady()).isEqualTo(false); // call requestMtu() if status is GATT_SUCCESS. mBassClientStateMachine.mDiscoveryInitiated = true; @@ -812,7 +809,7 @@ public class BassClientStateMachineTest { ArgumentCaptor.forClass(BluetoothLeBroadcastReceiveState.class); verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); mBassClientStateMachine.mPendingOperation = 0; mBassClientStateMachine.mPendingSourceId = 0; @@ -824,7 +821,7 @@ public class BassClientStateMachineTest { TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); mBassClientStateMachine.mPendingMetadata = createBroadcastMetadata(); sourceId = 1; @@ -881,7 +878,7 @@ public class BassClientStateMachineTest { verify(callbacks).notifySourceAdded(any(), any(), anyInt()); verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // set some values for covering more lines of processPASyncState() mBassClientStateMachine.mPendingMetadata = null; @@ -915,7 +912,7 @@ public class BassClientStateMachineTest { verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); assertThat(mBassClientStateMachine.mMsgWhats).contains(REMOVE_BCAST_SOURCE); mBassClientStateMachine.mIsPendingRemove = null; @@ -939,7 +936,7 @@ public class BassClientStateMachineTest { any(), anyInt(), eq(BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST)); verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); } @Test @@ -972,7 +969,7 @@ public class BassClientStateMachineTest { ArgumentCaptor<BluetoothLeBroadcastReceiveState> receiveStateCaptor = ArgumentCaptor.forClass(BluetoothLeBroadcastReceiveState.class); verify(callbacks).notifyReceiveStateChanged(any(), anyInt(), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); } @Test @@ -1104,7 +1101,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Read first time second (last) characteristic int sourceId2 = 2; @@ -1121,7 +1118,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId2), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); } /** This also tests BassClientStateMachine#processBroadcastReceiverState. */ @@ -1219,7 +1216,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Empty value to indicates removing source from device by remote when(characteristic.getValue()).thenReturn(new byte[] {}); @@ -1234,7 +1231,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); // Sync value again mBassClientStateMachine.mPendingOperation = ADD_BCAST_SOURCE; @@ -1249,7 +1246,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Empty value to indicates removing source from device by local app mBassClientStateMachine.mPendingOperation = REMOVE_BCAST_SOURCE; @@ -1265,7 +1262,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); // Sync value again mBassClientStateMachine.mPendingOperation = ADD_BCAST_SOURCE; @@ -1280,7 +1277,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Empty value to indicates removing source from device by stack (source switch) BluetoothLeBroadcastMetadata metadata = createBroadcastMetadata(); @@ -1297,7 +1294,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mEmptyTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mEmptyTestDevice); assertThat(mBassClientStateMachine.mMsgWhats).contains(ADD_BCAST_SOURCE); assertThat(mBassClientStateMachine.mMsgObj).isEqualTo(metadata); @@ -1314,7 +1311,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Update value - PA SyncInfo Request value[BassConstants.BCAST_RCVR_STATE_PA_SYNC_IDX] = @@ -1342,7 +1339,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Update value - PA SyncInfo Request, local broadcast mBassClientStateMachine.mPendingMetadata = createBroadcastMetadata(); @@ -1364,7 +1361,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Update value - Broadcast Code value[BassConstants.BCAST_RCVR_STATE_PA_SYNC_IDX] = @@ -1384,7 +1381,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); // Update value - Pending Remove value[BassConstants.BCAST_RCVR_STATE_PA_SYNC_IDX] = @@ -1401,7 +1398,7 @@ public class BassClientStateMachineTest { inOrderCallbacks .verify(callbacks) .notifyReceiveStateChanged(any(), eq(sourceId), receiveStateCaptor.capture()); - Assert.assertEquals(receiveStateCaptor.getValue().getSourceDevice(), mSourceTestDevice); + assertThat(receiveStateCaptor.getValue().getSourceDevice()).isEqualTo(mSourceTestDevice); } @Test @@ -1436,6 +1433,15 @@ public class BassClientStateMachineTest { BluetoothGattCallback cb = mBassClientStateMachine.mGattCallback; mBassClientStateMachine.mMTUChangeRequested = true; + BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class); + when(mBassClientService.getCallbacks()).thenReturn(callbacks); + + // Verify notifyBassStateSetupFailed is called + cb.onMtuChanged(null, 10, GATT_FAILURE); + verify(callbacks).notifyBassStateSetupFailed(eq(mBassClientStateMachine.getDevice())); + assertThat(mBassClientStateMachine.mMTUChangeRequested).isTrue(); + assertThat(mBassClientStateMachine.isBassStateReady()).isEqualTo(false); + cb.onMtuChanged(null, 10, GATT_SUCCESS); assertThat(mBassClientStateMachine.mMTUChangeRequested).isTrue(); @@ -1853,7 +1859,7 @@ public class BassClientStateMachineTest { BassClientStateMachine.ConnectedProcessing.class); verify(scanControlPoint).setValue(any(byte[].class)); verify(btGatt).writeCharacteristic(any()); - assertThat(mBassClientStateMachine.mPendingSourceToSwitch).isEqualTo(null); + assertThat(mBassClientStateMachine.mPendingSourceToSwitch).isNull(); } @Test @@ -2651,7 +2657,7 @@ public class BassClientStateMachineTest { verify(mMethodProxy, timeout(TIMEOUT_MS)) .periodicAdvertisingManagerRegisterSync( any(), any(), anyInt(), anyInt(), any(), any()); - Assert.assertEquals(mBassClientStateMachine.mPendingSourceToAdd, metadata); + assertThat(mBassClientStateMachine.mPendingSourceToAdd).isEqualTo(metadata); verify(mBassClientService, never()).sendBroadcast(any(Intent.class), anyString(), any()); } @@ -2778,7 +2784,7 @@ public class BassClientStateMachineTest { ArgumentCaptor.forClass(BluetoothLeBroadcastMetadata.class); verify(callbacks).notifySourceFound(metaData.capture()); - Assert.assertEquals(testRssi, metaData.getValue().getRssi()); + assertThat(metaData.getValue().getRssi()).isEqualTo(testRssi); } @Test @@ -2978,7 +2984,7 @@ public class BassClientStateMachineTest { TEST_SOURCE_ID, BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING, - BassConstants.BIS_SYNC_FAILED_SYNC_TO_BIG); + BassConstants.BCAST_RCVR_STATE_BIS_SYNC_FAILED_SYNC_TO_BIG); // Verify broadcast audio session is logged when bis sync failed verify(mMetricsLogger) .logLeAudioBroadcastAudioSync( @@ -3088,6 +3094,7 @@ public class BassClientStateMachineTest { 0x0L); // Verify notifyBassStateReady is called verify(callbacks).notifyBassStateReady(eq(mTestDevice)); + assertThat(mBassClientStateMachine.isBassStateReady()).isEqualTo(true); } @Test @@ -3179,6 +3186,69 @@ public class BassClientStateMachineTest { assertThat(mBassClientStateMachine.mPendingSourceId).isEqualTo(TEST_SOURCE_ID); } + @Test + public void updateBroadcastSource_withMetadataChanged() { + prepareInitialReceiveStateForGatt(); + + generateBroadcastReceiveStatesAndVerify( + mSourceTestDevice, + TEST_SOURCE_ID, + BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED, + BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING, + 0x1L); + + BassClientStateMachine.BluetoothGattTestableWrapper btGatt = + Mockito.mock(BassClientStateMachine.BluetoothGattTestableWrapper.class); + mBassClientStateMachine.mBluetoothGatt = btGatt; + BluetoothGattCharacteristic scanControlPoint = + Mockito.mock(BluetoothGattCharacteristic.class); + mBassClientStateMachine.mBroadcastScanControlPoint = scanControlPoint; + + BluetoothLeBroadcastMetadata metadata = createBroadcastMetadata(); + mBassClientStateMachine.mPendingMetadata = metadata; + + // Verify pausing broadcast stream with updated metadata + BluetoothLeBroadcastMetadata updatedMetadataPaused = getMetadataToPauseStream(metadata); + byte[] valueBisPaused = convertMetadataToUpdateSourceByteArray(updatedMetadataPaused); + + sendMessageAndVerifyTransition( + mBassClientStateMachine.obtainMessage( + UPDATE_BCAST_SOURCE, + TEST_SOURCE_ID, + BassConstants.INVALID_PA_SYNC_VALUE, + updatedMetadataPaused), + BassClientStateMachine.ConnectedProcessing.class); + assertThat(mBassClientStateMachine.mPendingOperation).isEqualTo(UPDATE_BCAST_SOURCE); + assertThat(mBassClientStateMachine.mPendingSourceId).isEqualTo(TEST_SOURCE_ID); + verify(scanControlPoint).setValue(eq(valueBisPaused)); + + sendMessageAndVerifyTransition( + mBassClientStateMachine.obtainMessage(GATT_TXN_PROCESSED), + BassClientStateMachine.Connected.class); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + Mockito.clearInvocations(scanControlPoint); + + // Verify resuming broadcast stream with the original metadata + byte[] valueBisResumed = convertMetadataToUpdateSourceByteArray(metadata); + sendMessageAndVerifyTransition( + mBassClientStateMachine.obtainMessage( + UPDATE_BCAST_SOURCE, + TEST_SOURCE_ID, + BassConstants.INVALID_PA_SYNC_VALUE, + metadata), + BassClientStateMachine.ConnectedProcessing.class); + assertThat(mBassClientStateMachine.mPendingOperation).isEqualTo(UPDATE_BCAST_SOURCE); + assertThat(mBassClientStateMachine.mPendingSourceId).isEqualTo(TEST_SOURCE_ID); + verify(scanControlPoint).setValue(eq(valueBisResumed)); + + sendMessageAndVerifyTransition( + mBassClientStateMachine.obtainMessage(GATT_TXN_PROCESSED), + BassClientStateMachine.Connected.class); + + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + Mockito.clearInvocations(scanControlPoint); + } + private void initToConnectingState() { allowConnection(true); allowConnectGatt(true); @@ -3258,7 +3328,7 @@ public class BassClientStateMachineTest { Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND)); } - Assert.assertThat(mBassClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); + assertThat(mBassClientStateMachine.getCurrentState()).isInstanceOf(type); } private BluetoothLeBroadcastMetadata createBroadcastMetadata() { @@ -3284,6 +3354,78 @@ public class BassClientStateMachineTest { return builder.build(); } + private byte[] convertMetadataToUpdateSourceByteArray(BluetoothLeBroadcastMetadata metaData) { + int numSubGroups = metaData.getSubgroups().size(); + + byte[] res = new byte[UPDATE_SOURCE_FIXED_LENGTH + numSubGroups * 5]; + int offset = 0; + // Opcode + res[offset++] = OPCODE_UPDATE_SOURCE; + // Source_ID + res[offset++] = (byte) TEST_SOURCE_ID; + // PA_Sync + res[offset++] = (byte) (0x01); + // PA_Interval + res[offset++] = (byte) 0xFF; + res[offset++] = (byte) 0xFF; + // Num_Subgroups + res[offset++] = (byte) numSubGroups; + + for (int i = 0; i < numSubGroups; i++) { + int bisIndexValue = 0; + for (BluetoothLeBroadcastChannel channel : + metaData.getSubgroups().get(i).getChannels()) { + if (channel.isSelected()) { + if (channel.getChannelIndex() == 0) { + continue; + } + bisIndexValue |= 1 << (channel.getChannelIndex() - 1); + } + } + // BIS_Sync + res[offset++] = (byte) (bisIndexValue & 0x00000000000000FF); + res[offset++] = (byte) ((bisIndexValue & 0x000000000000FF00) >>> 8); + res[offset++] = (byte) ((bisIndexValue & 0x0000000000FF0000) >>> 16); + res[offset++] = (byte) ((bisIndexValue & 0x00000000FF000000) >>> 24); + // Metadata_Length; On Modify source, don't update any Metadata + res[offset++] = 0; + } + return res; + } + + private BluetoothLeBroadcastMetadata getMetadataToPauseStream( + BluetoothLeBroadcastMetadata metadata) { + BluetoothLeBroadcastMetadata.Builder metadataToUpdateBuilder = + new BluetoothLeBroadcastMetadata.Builder(metadata); + + List<BluetoothLeBroadcastSubgroup> updatedSubgroups = new ArrayList<>(); + for (BluetoothLeBroadcastSubgroup subgroup : metadata.getSubgroups()) { + BluetoothLeBroadcastSubgroup.Builder subgroupBuilder = + new BluetoothLeBroadcastSubgroup.Builder(subgroup); + + List<BluetoothLeBroadcastChannel> updatedChannels = new ArrayList<>(); + for (BluetoothLeBroadcastChannel channel : subgroup.getChannels()) { + BluetoothLeBroadcastChannel updatedChannel = + new BluetoothLeBroadcastChannel.Builder(channel).setSelected(false).build(); + updatedChannels.add(updatedChannel); + } + + subgroupBuilder.clearChannel(); + for (BluetoothLeBroadcastChannel channel : updatedChannels) { + subgroupBuilder.addChannel(channel); + } + + updatedSubgroups.add(subgroupBuilder.build()); + } + + metadataToUpdateBuilder.clearSubgroup(); + for (BluetoothLeBroadcastSubgroup subgroup : updatedSubgroups) { + metadataToUpdateBuilder.addSubgroup(subgroup); + } + + return metadataToUpdateBuilder.build(); + } + private void prepareInitialReceiveStateForGatt() { initToConnectedState(); mBassClientStateMachine.connectGatt(true); @@ -3416,7 +3558,6 @@ public class BassClientStateMachineTest { // German language code in ISO 639-3 final String testLanguage = "deu"; final int testCodecId = 42; - final int testChannelIndex = 56; BluetoothLeAudioCodecConfigMetadata codecMetadata = new BluetoothLeAudioCodecConfigMetadata.Builder() @@ -3442,7 +3583,7 @@ public class BassClientStateMachineTest { BluetoothLeBroadcastChannel channel = new BluetoothLeBroadcastChannel.Builder() .setSelected(true) - .setChannelIndex(testChannelIndex) + .setChannelIndex(TEST_CHANNEL_INDEX) .setCodecMetadata(channelCodecMetadata) .build(); builder.addChannel(channel); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index 1d7e3a2c2d..c81c611336 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -63,7 +63,6 @@ import com.android.bluetooth.hfp.HeadsetService; import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; -import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; @@ -288,7 +287,7 @@ public class ActiveDeviceManagerTest { // Don't call mA2dpService.setActiveDevice() mTestLooper.dispatchAll(); verify(mA2dpService).setActiveDevice(mA2dpDevice); - Assert.assertEquals(mA2dpDevice, mActiveDeviceManager.getA2dpActiveDevice()); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isEqualTo(mA2dpDevice); } /** @@ -358,7 +357,7 @@ public class ActiveDeviceManagerTest { // Don't call mHeadsetService.setActiveDevice() mTestLooper.dispatchAll(); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); - Assert.assertEquals(mHeadsetDevice, mActiveDeviceManager.getHfpActiveDevice()); + assertThat(mActiveDeviceManager.getHfpActiveDevice()).isEqualTo(mHeadsetDevice); } /** @@ -589,7 +588,6 @@ public class ActiveDeviceManagerTest { } @Test - @EnableFlags(Flags.FLAG_ADM_ALWAYS_FALLBACK_TO_AVAILABLE_DEVICE) public void a2dpHeadsetActivated_checkFallbackMeachanismOneA2dpOneHeadset() { // Active call when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL); @@ -621,7 +619,7 @@ public class ActiveDeviceManagerTest { a2dpActiveDeviceChanged(null); mTestLooper.dispatchAll(); - assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isEqualTo(null); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isNull(); assertThat(mActiveDeviceManager.getHfpActiveDevice()).isEqualTo(mA2dpHeadsetDevice); // Connect 2nd device @@ -807,7 +805,7 @@ public class ActiveDeviceManagerTest { verify(mHearingAidService).removeActiveDevice(false); // Don't call mA2dpService.setActiveDevice() verify(mA2dpService, never()).setActiveDevice(mA2dpDevice); - Assert.assertEquals(mA2dpDevice, mActiveDeviceManager.getA2dpActiveDevice()); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isEqualTo(mA2dpDevice); assertThat(mActiveDeviceManager.getHearingAidActiveDevices()).isEmpty(); } @@ -826,7 +824,7 @@ public class ActiveDeviceManagerTest { verify(mHearingAidService).removeActiveDevice(false); // Don't call mHeadsetService.setActiveDevice() verify(mHeadsetService, never()).setActiveDevice(mHeadsetDevice); - Assert.assertEquals(mHeadsetDevice, mActiveDeviceManager.getHfpActiveDevice()); + assertThat(mActiveDeviceManager.getHfpActiveDevice()).isEqualTo(mHeadsetDevice); assertThat(mActiveDeviceManager.getHearingAidActiveDevices()).isEmpty(); } @@ -975,7 +973,7 @@ public class ActiveDeviceManagerTest { // Don't call mLeAudioService.setActiveDevice() mTestLooper.dispatchAll(); verify(mLeAudioService, never()).setActiveDevice(any(BluetoothDevice.class)); - Assert.assertEquals(mLeAudioDevice, mActiveDeviceManager.getLeAudioActiveDevice()); + assertThat(mActiveDeviceManager.getLeAudioActiveDevice()).isEqualTo(mLeAudioDevice); } /** @@ -1203,7 +1201,7 @@ public class ActiveDeviceManagerTest { mTestLooper.dispatchAll(); verify(mLeAudioService).removeActiveDevice(true); verify(mA2dpService).setActiveDevice(mA2dpDevice); - Assert.assertEquals(mA2dpDevice, mActiveDeviceManager.getA2dpActiveDevice()); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isEqualTo(mA2dpDevice); assertThat(mActiveDeviceManager.getLeAudioActiveDevice()).isNull(); } @@ -1221,7 +1219,7 @@ public class ActiveDeviceManagerTest { mTestLooper.dispatchAll(); verify(mLeAudioService).removeActiveDevice(true); verify(mHeadsetService).setActiveDevice(mHeadsetDevice); - Assert.assertEquals(mHeadsetDevice, mActiveDeviceManager.getHfpActiveDevice()); + assertThat(mActiveDeviceManager.getHfpActiveDevice()).isEqualTo(mHeadsetDevice); assertThat(mActiveDeviceManager.getLeAudioActiveDevice()).isNull(); } @@ -1585,8 +1583,8 @@ public class ActiveDeviceManagerTest { verify(mA2dpService, atLeastOnce()).setActiveDevice(mDualModeAudioDevice); verify(mHeadsetService, atLeastOnce()).setActiveDevice(mDualModeAudioDevice); verify(mLeAudioService, atLeastOnce()).removeActiveDevice(true); - Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getA2dpActiveDevice()); - Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getHfpActiveDevice()); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isEqualTo(mDualModeAudioDevice); + assertThat(mActiveDeviceManager.getHfpActiveDevice()).isEqualTo(mDualModeAudioDevice); // Ensure we make classic audio profiles inactive when LEA is made active leAudioConnected(mDualModeAudioDevice); @@ -1594,7 +1592,7 @@ public class ActiveDeviceManagerTest { verify(mA2dpService).removeActiveDevice(false); verify(mHeadsetService).setActiveDevice(isNull()); verify(mLeAudioService).setActiveDevice(mDualModeAudioDevice); - Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getLeAudioActiveDevice()); + assertThat(mActiveDeviceManager.getLeAudioActiveDevice()).isEqualTo(mDualModeAudioDevice); } /** @@ -1638,15 +1636,15 @@ public class ActiveDeviceManagerTest { verify(mLeAudioService, never()).removeActiveDevice(anyBoolean()); verify(mLeAudioService).setActiveDevice(mDualModeAudioDevice); - Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getA2dpActiveDevice()); - Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getHfpActiveDevice()); - Assert.assertEquals(mDualModeAudioDevice, mActiveDeviceManager.getLeAudioActiveDevice()); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isEqualTo(mDualModeAudioDevice); + assertThat(mActiveDeviceManager.getHfpActiveDevice()).isEqualTo(mDualModeAudioDevice); + assertThat(mActiveDeviceManager.getLeAudioActiveDevice()).isEqualTo(mDualModeAudioDevice); // Verify LEA made inactive when a supported classic audio profile is made inactive a2dpActiveDeviceChanged(null); mTestLooper.dispatchAll(); - Assert.assertEquals(null, mActiveDeviceManager.getA2dpActiveDevice()); - Assert.assertEquals(null, mActiveDeviceManager.getLeAudioActiveDevice()); + assertThat(mActiveDeviceManager.getA2dpActiveDevice()).isNull(); + assertThat(mActiveDeviceManager.getLeAudioActiveDevice()).isNull(); } /** @@ -1721,7 +1719,6 @@ public class ActiveDeviceManagerTest { /** A wired audio device is disconnected. Check if falls back to connected A2DP. */ @Test - @EnableFlags(Flags.FLAG_ADM_FALLBACK_WHEN_WIRED_AUDIO_DISCONNECTED) public void wiredAudioDeviceDisconnected_setFallbackDevice() throws Exception { AudioDeviceInfo[] testDevices = createAudioDeviceInfoTestDevices(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java index f24c1ff2aa..cc40c6af72 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java @@ -40,7 +40,6 @@ import com.android.bluetooth.TestUtils; import com.android.bluetooth.Utils; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -587,7 +586,7 @@ public class BondStateMachineTest { // Properties are removed when bond is removed if (newState != BluetoothDevice.BOND_NONE) { - Assert.assertEquals(expectedNewState, mDeviceProperties.getBondState()); + assertThat(mDeviceProperties.getBondState()).isEqualTo(expectedNewState); } // Check for bond state Intent status. @@ -739,16 +738,17 @@ public class BondStateMachineTest { private void verifyBondStateChangeIntent(int oldState, int newState, Intent intent) { assertThat(intent).isNotNull(); - Assert.assertEquals(BluetoothDevice.ACTION_BOND_STATE_CHANGED, intent.getAction()); - Assert.assertEquals(mDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(newState, intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)); - Assert.assertEquals( - oldState, intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1)); + assertThat(intent.getAction()).isEqualTo(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(mDevice); + assertThat(intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)).isEqualTo(newState); + assertThat(intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1)) + .isEqualTo(oldState); if (newState == BOND_NONE) { - Assert.assertEquals( - TEST_BOND_REASON, intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON, -1)); + assertThat(intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON, -1)) + .isEqualTo(TEST_BOND_REASON); } else { - Assert.assertEquals(-1, intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON, -1)); + assertThat(intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON, -1)).isEqualTo(-1); } } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java index aa49e0d0a7..a46a805941 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java @@ -34,7 +34,6 @@ import com.google.common.hash.Funnels; import com.google.protobuf.InvalidProtocolBufferException; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -132,15 +131,15 @@ public class MetricsLoggerTest { BluetoothLog.Builder metricsBuilder = BluetoothLog.newBuilder(); MetricsLogger.dumpProto(metricsBuilder); BluetoothLog metricsProto = metricsBuilder.build(); - Assert.assertEquals(1, metricsProto.getProfileConnectionStatsCount()); + assertThat(metricsProto.getProfileConnectionStatsCount()).isEqualTo(1); ProfileConnectionStats profileUsageStatsAvrcp = metricsProto.getProfileConnectionStats(0); - Assert.assertEquals(ProfileId.AVRCP, profileUsageStatsAvrcp.getProfileId()); - Assert.assertEquals(1, profileUsageStatsAvrcp.getNumTimesConnected()); + assertThat(profileUsageStatsAvrcp.getProfileId()).isEqualTo(ProfileId.AVRCP); + assertThat(profileUsageStatsAvrcp.getNumTimesConnected()).isEqualTo(1); // Verify that MetricsLogger's internal state is cleared after a dump BluetoothLog.Builder metricsBuilderAfterDump = BluetoothLog.newBuilder(); MetricsLogger.dumpProto(metricsBuilderAfterDump); BluetoothLog metricsProtoAfterDump = metricsBuilderAfterDump.build(); - Assert.assertEquals(0, metricsProtoAfterDump.getProfileConnectionStatsCount()); + assertThat(metricsProtoAfterDump.getProfileConnectionStatsCount()).isEqualTo(0); } /** Test whether multiple profile's connection events can be logged interleaving */ @@ -152,20 +151,20 @@ public class MetricsLoggerTest { BluetoothLog.Builder metricsBuilder = BluetoothLog.newBuilder(); MetricsLogger.dumpProto(metricsBuilder); BluetoothLog metricsProto = metricsBuilder.build(); - Assert.assertEquals(2, metricsProto.getProfileConnectionStatsCount()); + assertThat(metricsProto.getProfileConnectionStatsCount()).isEqualTo(2); Map<ProfileId, ProfileConnectionStats> profileConnectionCountMap = getProfileUsageStatsMap(metricsProto.getProfileConnectionStatsList()); assertThat(profileConnectionCountMap).containsKey(ProfileId.AVRCP); - Assert.assertEquals( - 2, profileConnectionCountMap.get(ProfileId.AVRCP).getNumTimesConnected()); + assertThat(profileConnectionCountMap.get(ProfileId.AVRCP).getNumTimesConnected()) + .isEqualTo(2); assertThat(profileConnectionCountMap).containsKey(ProfileId.HEADSET); - Assert.assertEquals( - 1, profileConnectionCountMap.get(ProfileId.HEADSET).getNumTimesConnected()); + assertThat(profileConnectionCountMap.get(ProfileId.HEADSET).getNumTimesConnected()) + .isEqualTo(1); // Verify that MetricsLogger's internal state is cleared after a dump BluetoothLog.Builder metricsBuilderAfterDump = BluetoothLog.newBuilder(); MetricsLogger.dumpProto(metricsBuilderAfterDump); BluetoothLog metricsProtoAfterDump = metricsBuilderAfterDump.build(); - Assert.assertEquals(0, metricsProtoAfterDump.getProfileConnectionStatsCount()); + assertThat(metricsProtoAfterDump.getProfileConnectionStatsCount()).isEqualTo(0); } private static Map<ProfileId, ProfileConnectionStats> getProfileUsageStatsMap( @@ -183,17 +182,17 @@ public class MetricsLoggerTest { mTestableMetricsLogger.cacheCount(2, 5); mTestableMetricsLogger.drainBufferedCounters(); - Assert.assertEquals(20L, mTestableMetricsLogger.mTestableCounters.get(1).longValue()); - Assert.assertEquals(5L, mTestableMetricsLogger.mTestableCounters.get(2).longValue()); + assertThat(mTestableMetricsLogger.mTestableCounters.get(1).longValue()).isEqualTo(20L); + assertThat(mTestableMetricsLogger.mTestableCounters.get(2).longValue()).isEqualTo(5L); mTestableMetricsLogger.cacheCount(1, 3); mTestableMetricsLogger.cacheCount(2, 5); mTestableMetricsLogger.cacheCount(2, 5); mTestableMetricsLogger.cacheCount(3, 1); mTestableMetricsLogger.drainBufferedCounters(); - Assert.assertEquals(3L, mTestableMetricsLogger.mTestableCounters.get(1).longValue()); - Assert.assertEquals(10L, mTestableMetricsLogger.mTestableCounters.get(2).longValue()); - Assert.assertEquals(1L, mTestableMetricsLogger.mTestableCounters.get(3).longValue()); + assertThat(mTestableMetricsLogger.mTestableCounters.get(1).longValue()).isEqualTo(3L); + assertThat(mTestableMetricsLogger.mTestableCounters.get(2).longValue()).isEqualTo(10L); + assertThat(mTestableMetricsLogger.mTestableCounters.get(3).longValue()).isEqualTo(1L); } @Test @@ -207,8 +206,8 @@ public class MetricsLoggerTest { assertThat(mTestableMetricsLogger.mTestableCounters).doesNotContainKey(1); assertThat(mTestableMetricsLogger.mTestableCounters).doesNotContainKey(3); - Assert.assertEquals( - Long.MAX_VALUE, mTestableMetricsLogger.mTestableCounters.get(2).longValue()); + assertThat(mTestableMetricsLogger.mTestableCounters.get(2).longValue()) + .isEqualTo(Long.MAX_VALUE); } @Test @@ -218,9 +217,9 @@ public class MetricsLoggerTest { mTestableMetricsLogger.cacheCount(2, Long.MAX_VALUE); mTestableMetricsLogger.close(); - Assert.assertEquals(1, mTestableMetricsLogger.mTestableCounters.get(1).longValue()); - Assert.assertEquals( - Long.MAX_VALUE, mTestableMetricsLogger.mTestableCounters.get(2).longValue()); + assertThat(mTestableMetricsLogger.mTestableCounters.get(1).longValue()).isEqualTo(1); + assertThat(mTestableMetricsLogger.mTestableCounters.get(2).longValue()) + .isEqualTo(Long.MAX_VALUE); } @Test @@ -244,10 +243,8 @@ public class MetricsLoggerTest { for (Map.Entry<String, String> entry : SANITIZED_DEVICE_NAME_MAP.entrySet()) { String deviceName = entry.getKey(); String sha256 = MetricsLogger.getSha256String(entry.getValue()); - Assert.assertEquals( - deviceName, - sha256, - mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, deviceName)); + assertThat(mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, deviceName)) + .isEqualTo(sha256); } } @@ -263,7 +260,7 @@ public class MetricsLoggerTest { BluetoothRemoteDeviceInformation bluetoothRemoteDeviceInformation = BluetoothRemoteDeviceInformation.parseFrom(remoteDeviceInformationBytes); int oui = (0 << 16) | (1 << 8) | 2; // OUI from the above mac address - Assert.assertEquals(bluetoothRemoteDeviceInformation.getOui(), oui); + assertThat(bluetoothRemoteDeviceInformation.getOui()).isEqualTo(oui); } catch (InvalidProtocolBufferException e) { assertThat(e.getMessage()).isNull(); // test failure here @@ -278,7 +275,7 @@ public class MetricsLoggerTest { String actualMedicalDeviceSha256 = mTestableMetricsLogger.getAllowlistedDeviceNameHash(deviceName, true); - Assert.assertEquals(expectMedicalDeviceSha256, actualMedicalDeviceSha256); + assertThat(actualMedicalDeviceSha256).isEqualTo(expectMedicalDeviceSha256); } @Test @@ -289,13 +286,13 @@ public class MetricsLoggerTest { String actualMedicalDeviceSha256 = mTestableMetricsLogger.getAllowlistedDeviceNameHash(deviceName, false); - Assert.assertEquals(expectMedicalDeviceSha256, actualMedicalDeviceSha256); + assertThat(actualMedicalDeviceSha256).isEqualTo(expectMedicalDeviceSha256); } @Test public void uploadEmptyDeviceName() throws IOException { initTestingBloomfilter(); - Assert.assertEquals("", mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, "")); + assertThat(mTestableMetricsLogger.logAllowlistedDeviceNameHash(1, "")).isEmpty(); } private void initTestingBloomfilter() throws IOException { diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java index 2e7225e74b..9ca563774f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java @@ -44,10 +44,8 @@ import com.android.bluetooth.hfpclient.NativeInterface; import com.android.bluetooth.hid.HidDeviceNativeInterface; import com.android.bluetooth.hid.HidHostNativeInterface; import com.android.bluetooth.le_audio.LeAudioNativeInterface; -import com.android.bluetooth.pan.PanNativeInterface; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -89,7 +87,6 @@ public class ProfileServiceTest { @Mock private HearingAidNativeInterface mHearingAidNativeInterface; @Mock private HidDeviceNativeInterface mHidDeviceNativeInterface; @Mock private HidHostNativeInterface mHidHostNativeInterface; - @Mock private PanNativeInterface mPanNativeInterface; @Mock private LeAudioNativeInterface mLeAudioInterface; private void setProfileState(int profile, int state) { @@ -121,9 +118,7 @@ public class ProfileServiceTest { .collect(Collectors.groupingBy(Object::getClass, Collectors.counting())); counts.forEach( - (clazz, count) -> - Assert.assertEquals( - clazz.getSimpleName(), (long) invocationNumber, count.longValue())); + (clazz, count) -> assertThat((long) invocationNumber).isEqualTo(count.longValue())); } @Before @@ -155,6 +150,7 @@ public class ProfileServiceTest { && profile != BluetoothProfile.VOLUME_CONTROL && profile != BluetoothProfile.CSIP_SET_COORDINATOR && profile != BluetoothProfile.GATT + && profile != BluetoothProfile.PAN && profile != BluetoothProfile.A2DP) .toArray(); TestUtils.setAdapterService(mAdapterService); @@ -169,7 +165,6 @@ public class ProfileServiceTest { HearingAidNativeInterface.setInstance(mHearingAidNativeInterface); HidDeviceNativeInterface.setInstance(mHidDeviceNativeInterface); HidHostNativeInterface.setInstance(mHidHostNativeInterface); - PanNativeInterface.setInstance(mPanNativeInterface); LeAudioNativeInterface.setInstance(mLeAudioInterface); } @@ -187,7 +182,6 @@ public class ProfileServiceTest { HearingAidNativeInterface.setInstance(null); HidDeviceNativeInterface.setInstance(null); HidHostNativeInterface.setInstance(null); - PanNativeInterface.setInstance(null); LeAudioNativeInterface.setInstance(null); } @@ -236,7 +230,7 @@ public class ProfileServiceTest { List<ProfileService> startedArguments = starts.getAllValues(); List<ProfileService> stoppedArguments = stops.getAllValues(); - Assert.assertEquals(startedArguments.size(), stoppedArguments.size()); + assertThat(startedArguments.size()).isEqualTo(stoppedArguments.size()); for (ProfileService service : startedArguments) { assertThat(stoppedArguments).contains(service); stoppedArguments.remove(service); @@ -263,7 +257,7 @@ public class ProfileServiceTest { verify(mAdapterService, times(NUM_REPEATS * profileNumber + i + 1)) .onProfileServiceStateChanged( stop.capture(), eq(BluetoothAdapter.STATE_OFF)); - Assert.assertEquals(start.getValue(), stop.getValue()); + assertThat(start.getValue()).isEqualTo(stop.getValue()); } profileNumber += 1; } @@ -287,7 +281,7 @@ public class ProfileServiceTest { ArgumentCaptor<ProfileService> stop = ArgumentCaptor.forClass(ProfileService.class); verify(mAdapterService, times(NUM_REPEATS * profileNumber + i + 1)) .removeProfile(stop.capture()); - Assert.assertEquals(start.getValue(), stop.getValue()); + assertThat(start.getValue()).isEqualTo(stop.getValue()); } profileNumber += 1; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java index 28747da680..f9d4d0f045 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java @@ -33,7 +33,6 @@ import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.HeadsetHalConstants; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -123,12 +122,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that update same battery level for the same device does not trigger intent mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel, /* fromBas= */ false); @@ -140,12 +139,12 @@ public class RemoteDevicesTest { verify(mAdapterService, times(2)) .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); // Verify that user can get battery level after the update - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); verifyNoMoreInteractions(mAdapterService); } @@ -209,12 +208,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that resetting battery level changes it back to BluetoothDevice // .BATTERY_LEVEL_UNKNOWN @@ -225,12 +224,11 @@ public class RemoteDevicesTest { mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent( mDevice1, BluetoothDevice.BATTERY_LEVEL_UNKNOWN, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify value is reset in properties assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), - BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); // Verify no intent is sent after second reset mRemoteDevices.resetBatteryLevel(mDevice1, /* fromBas= */ false); @@ -242,7 +240,7 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); verifyNoMoreInteractions(mAdapterService); } @@ -260,12 +258,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that resetting battery level changes it back to BluetoothDevice // .BATTERY_LEVEL_UNKNOWN @@ -279,12 +277,11 @@ public class RemoteDevicesTest { mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent( mDevice1, BluetoothDevice.BATTERY_LEVEL_UNKNOWN, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify value is reset in properties assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), - BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); // Verify that updating battery level triggers ACTION_BATTERY_LEVEL_CHANGED intent again mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel, /* fromBas= */ false); @@ -292,7 +289,7 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); verifyNoMoreInteractions(mAdapterService); } @@ -313,12 +310,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that battery level is not reset mRemoteDevices.onHeadsetConnectionStateChanged( @@ -327,8 +324,8 @@ public class RemoteDevicesTest { BluetoothProfile.STATE_DISCONNECTED); assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - batteryLevel, mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Recover the previous battery service if exists clearBatteryServiceForTesting(oldBatteryService); @@ -350,12 +347,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - batteryLevel, mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that when device is completely disconnected, RemoteDevices reset battery level to // BluetoothDevice.BATTERY_LEVEL_UNKNOWN @@ -376,17 +373,15 @@ public class RemoteDevicesTest { mDevice1, BluetoothDevice.BATTERY_LEVEL_UNKNOWN, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 2)); - Assert.assertEquals( - BLUETOOTH_CONNECT, - mStringArgument.getAllValues().get(mStringArgument.getAllValues().size() - 2)); - Assert.assertEquals( - BluetoothDevice.ACTION_ACL_DISCONNECTED, mIntentArgument.getValue().getAction()); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getAllValues().get(mStringArgument.getAllValues().size() - 2)) + .isEqualTo(BLUETOOTH_CONNECT); + assertThat(mIntentArgument.getValue().getAction()) + .isEqualTo(BluetoothDevice.ACTION_ACL_DISCONNECTED); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify value is reset in properties assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); // Verify that updating battery level triggers ACTION_BATTERY_LEVEL_CHANGED intent again mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel, /* fromBas= */ false); @@ -394,7 +389,7 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); } @Test @@ -411,7 +406,7 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); } @Test @@ -444,7 +439,7 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, 42, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); } @Test @@ -471,107 +466,102 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, 60, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); } @Test public void testGetBatteryLevelFromXEventVsc() { - Assert.assertEquals(42, RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(3, 8))); - Assert.assertEquals( - 100, RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(10, 11))); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(1, 1))); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(3, 1))); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(-1, 1))); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(-1, -1))); + assertThat(RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(3, 8))).isEqualTo(42); + assertThat(RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(10, 11))) + .isEqualTo(100); + assertThat(RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(1, 1))) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(3, 1))) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(-1, 1))) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(RemoteDevices.getBatteryLevelFromXEventVsc(getXEventArray(-1, -1))) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); } @Test public void testGetBatteryLevelFromAppleBatteryVsc() { - Assert.assertEquals( - 10, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 1, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - 0 - })); - Assert.assertEquals( - 100, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 1, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - 9 - })); - Assert.assertEquals( - 60, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 3, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - 5, - 2, - 1, - 3, - 10 - })); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 3, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - 5, - 2, - 1, - 3 - })); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 1, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - 10 - })); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 1, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - -1 - })); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] { - 1, - BluetoothHeadset - .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, - "5" - })); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc(new Object[] {1, 35, 37})); - Assert.assertEquals( - BluetoothDevice.BATTERY_LEVEL_UNKNOWN, - RemoteDevices.getBatteryLevelFromAppleBatteryVsc( - new Object[] {1, "WRONG", "WRONG"})); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 1, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + 0 + })) + .isEqualTo(10); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 1, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + 9 + })) + .isEqualTo(100); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 3, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + 5, + 2, + 1, + 3, + 10 + })) + .isEqualTo(60); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 3, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + 5, + 2, + 1, + 3 + })) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 1, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + 10 + })) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 1, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + -1 + })) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] { + 1, + BluetoothHeadset + .VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV_BATTERY_LEVEL, + "5" + })) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(RemoteDevices.getBatteryLevelFromAppleBatteryVsc(new Object[] {1, 35, 37})) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat( + RemoteDevices.getBatteryLevelFromAppleBatteryVsc( + new Object[] {1, "WRONG", "WRONG"})) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); } @Test @@ -587,12 +577,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that resetting battery level changes it back to BluetoothDevice // .BATTERY_LEVEL_UNKNOWN @@ -607,13 +597,12 @@ public class RemoteDevicesTest { mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent( mDevice1, BluetoothDevice.BATTERY_LEVEL_UNKNOWN, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify value is reset in properties assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), - BluetoothDevice.BATTERY_LEVEL_UNKNOWN); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(BluetoothDevice.BATTERY_LEVEL_UNKNOWN); // Verify that updating battery level triggers ACTION_BATTERY_LEVEL_CHANGED intent again mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel, /* fromBas= */ false); @@ -621,7 +610,7 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); verifyNoMoreInteractions(mAdapterService); } @@ -642,12 +631,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that battery level is not reset. mRemoteDevices.onHeadsetClientConnectionStateChanged( @@ -656,8 +645,8 @@ public class RemoteDevicesTest { BluetoothProfile.STATE_DISCONNECTED); assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - batteryLevel, mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); clearBatteryServiceForTesting(oldBatteryService); @@ -681,12 +670,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that updating battery service overrides hfp battery level mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel2, /* fromBas= */ true); @@ -697,8 +686,8 @@ public class RemoteDevicesTest { // Verify that the battery level isn't reset mRemoteDevices.resetBatteryLevel(mDevice1, /* fromBas= */ true); - Assert.assertEquals( - batteryLevel, mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); verify(mAdapterService, times(3)) .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); @@ -725,12 +714,12 @@ public class RemoteDevicesTest { .sendBroadcast( mIntentArgument.capture(), mStringArgument.capture(), any(Bundle.class)); verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); // Verify that user can get battery level after the update assertThat(mRemoteDevices.getDeviceProperties(mDevice1)).isNotNull(); - Assert.assertEquals( - mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel(), batteryLevel); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); // Verify that updating battery service doesn't send broadcast mRemoteDevices.updateBatteryLevel(mDevice1, batteryLevel, /* fromBas= */ true); @@ -738,8 +727,8 @@ public class RemoteDevicesTest { // Verify that the battery level isn't reset mRemoteDevices.resetBatteryLevel(mDevice1, /* fromBas= */ true); - Assert.assertEquals( - batteryLevel, mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getBatteryLevel()) + .isEqualTo(batteryLevel); verifyNoMoreInteractions(mAdapterService); clearBatteryServiceForTesting(oldBatteryService); @@ -763,7 +752,7 @@ public class RemoteDevicesTest { mDevice1, RemoteDevices.batteryChargeIndicatorToPercentge(batteryLevel), mIntentArgument); - Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue()); + assertThat(mStringArgument.getValue()).isEqualTo(BLUETOOTH_CONNECT); } @Test @@ -775,7 +764,7 @@ public class RemoteDevicesTest { mRemoteDevices.addDeviceProperties(Utils.getBytesFromAddress(TEST_BT_ADDR_1)); DeviceProperties prop2 = mRemoteDevices.addDeviceProperties(Utils.getBytesFromAddress(TEST_BT_ADDR_1)); - Assert.assertEquals(prop2, prop1); + assertThat(prop1).isEqualTo(prop2); } @Test @@ -796,9 +785,8 @@ public class RemoteDevicesTest { deviceProp.setHfAudioPolicyForRemoteAg(policies); // Verify that the audio policy properties are set and get properly - Assert.assertEquals( - policies, - mRemoteDevices.getDeviceProperties(mDevice1).getHfAudioPolicyForRemoteAg()); + assertThat(mRemoteDevices.getDeviceProperties(mDevice1).getHfAudioPolicyForRemoteAg()) + .isEqualTo(policies); } @Test @@ -845,14 +833,15 @@ public class RemoteDevicesTest { private static void verifyBatteryLevelChangedIntent( BluetoothDevice device, int batteryLevel, Intent intent) { - Assert.assertEquals(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, intent.getAction()); - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals( - batteryLevel, intent.getIntExtra(BluetoothDevice.EXTRA_BATTERY_LEVEL, -15)); - Assert.assertEquals( - Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, - intent.getFlags()); + assertThat(intent.getAction()).isEqualTo(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(device); + assertThat(intent.getIntExtra(BluetoothDevice.EXTRA_BATTERY_LEVEL, -15)) + .isEqualTo(batteryLevel); + assertThat(intent.getFlags()) + .isEqualTo( + Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); } private static Object[] getXEventArray(int batteryLevel, int numLevels) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java index c616c90aa7..593e422776 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java @@ -39,7 +39,6 @@ import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.hfp.HeadsetService; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -122,7 +121,7 @@ public class SilenceDeviceManagerTest { // Set silence state and check whether state changed successfully assertThat(mSilenceDeviceManager.setSilenceMode(mTestDevice, enableSilence)).isTrue(); TestUtils.waitForLooperToFinishScheduledTask(mLooper); - Assert.assertEquals(enableSilence, mSilenceDeviceManager.getSilenceMode(mTestDevice)); + assertThat(mSilenceDeviceManager.getSilenceMode(mTestDevice)).isEqualTo(enableSilence); // Check for silence state changed intent if (wasSilenced != enableSilence) { @@ -163,8 +162,9 @@ public class SilenceDeviceManagerTest { } void verifySilenceStateIntent(Intent intent) { - Assert.assertEquals(BluetoothDevice.ACTION_SILENCE_MODE_CHANGED, intent.getAction()); - Assert.assertEquals(mTestDevice, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); + assertThat(intent.getAction()).isEqualTo(BluetoothDevice.ACTION_SILENCE_MODE_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(mTestDevice); } /** Helper to indicate A2dp connected for a device. */ diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java index 668743ad31..93ce02664c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java @@ -155,14 +155,6 @@ public final class BluetoothKeystoreServiceTest { "aec555555555555555555555555555555555555555555555"); } - private boolean doCompareKeySet(Map<String, String> map1, Map<String, String> map2) { - return map1.keySet().equals(map2.keySet()); - } - - private boolean doCompareMap(Map<String, String> map1, Map<String, String> map2) { - return map1.equals(map2); - } - private boolean parseConfigFile(String filePathString) { try { mBluetoothKeystoreService.parseConfigFile(filePathString); @@ -205,11 +197,7 @@ public final class BluetoothKeystoreServiceTest { // load config file. assertThat(parseConfigFile(CONFIG_FILE_PATH)).isTrue(); // make sure it is same with createNameDecryptKeyResult - assertThat( - doCompareMap( - mNameDecryptKeyResult, - mBluetoothKeystoreService.getNameDecryptKey())) - .isTrue(); + assertThat(mBluetoothKeystoreService.getNameDecryptKey()).isEqualTo(mNameDecryptKeyResult); } @Test @@ -219,11 +207,8 @@ public final class BluetoothKeystoreServiceTest { // Wait for encryption to complete mBluetoothKeystoreService.stopThread(); - assertThat( - doCompareKeySet( - mNameDecryptKeyResult, - mBluetoothKeystoreService.getNameEncryptKey())) - .isTrue(); + assertThat(mBluetoothKeystoreService.getNameDecryptKey().keySet()) + .containsExactlyElementsIn(mNameDecryptKeyResult.keySet()); } @Test @@ -238,11 +223,7 @@ public final class BluetoothKeystoreServiceTest { // Wait for encryption to complete mBluetoothKeystoreService.stopThread(); - assertThat( - doCompareMap( - mNameDecryptKeyResult, - mBluetoothKeystoreService.getNameDecryptKey())) - .isTrue(); + assertThat(mBluetoothKeystoreService.getNameDecryptKey()).isEqualTo(mNameDecryptKeyResult); } @Test @@ -279,11 +260,7 @@ public final class BluetoothKeystoreServiceTest { // remove hash data avoid interfering result. mBluetoothKeystoreService.getNameDecryptKey().remove(CONFIG_FILE_PREFIX); - assertThat( - doCompareMap( - mNameDecryptKeyResult, - mBluetoothKeystoreService.getNameDecryptKey())) - .isTrue(); + assertThat(mBluetoothKeystoreService.getNameDecryptKey()).isEqualTo(mNameDecryptKeyResult); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java index bcaccfd94f..97263581da 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java @@ -152,18 +152,15 @@ public final class DatabaseManagerTest { restartDatabaseManagerHelper(); for (int id = 0; id < BluetoothProfile.MAX_PROFILE_ID; id++) { - Assert.assertEquals( - BluetoothProfile.CONNECTION_POLICY_UNKNOWN, - mDatabaseManager.getProfileConnectionPolicy(mTestDevice, id)); + assertThat(mDatabaseManager.getProfileConnectionPolicy(mTestDevice, id)) + .isEqualTo(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); } - Assert.assertEquals( - BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN, - mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice)); + assertThat(mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice)) + .isEqualTo(BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN); - Assert.assertEquals( - BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN, - mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice)); + assertThat(mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice)) + .isEqualTo(BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN); for (int id = 0; id < MAX_META_ID; id++) { assertThat(mDatabaseManager.getCustomMeta(mTestDevice, id)).isNull(); @@ -340,11 +337,11 @@ public final class DatabaseManagerTest { List<Metadata> list = mDatabase.load(); // Check number of metadata in the database - Assert.assertEquals(1, list.size()); + assertThat(list.size()).isEqualTo(1); // Check whether the device is in database Metadata checkData = list.get(0); - Assert.assertEquals(TEST_BT_ADDR, checkData.getAddress()); + assertThat(checkData.getAddress()).isEqualTo(TEST_BT_ADDR); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); @@ -388,13 +385,13 @@ public final class DatabaseManagerTest { // Check number of metadata in the database List<Metadata> list = mDatabase.load(); // OTHER_BT_ADDR1 and OTHER_BT_ADDR2 should still in database - Assert.assertEquals(2, list.size()); + assertThat(list.size()).isEqualTo(2); // Check whether the devices are in the database Metadata checkData1 = list.get(0); - Assert.assertEquals(OTHER_BT_ADDR2, checkData1.getAddress()); + assertThat(checkData1.getAddress()).isEqualTo(OTHER_BT_ADDR2); Metadata checkData2 = list.get(1); - Assert.assertEquals(OTHER_BT_ADDR1, checkData2.getAddress()); + assertThat(checkData2.getAddress()).isEqualTo(OTHER_BT_ADDR1); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); @@ -522,7 +519,7 @@ public final class DatabaseManagerTest { public void testSetConnectionHeadset() { mSetFlagsRule.disableFlags(Flags.FLAG_AUTO_CONNECT_ON_MULTIPLE_HFP_WHEN_NO_A2DP_DEVICE); // Verify pre-conditions to ensure a fresh test - Assert.assertEquals(0, mDatabaseManager.mMetadataCache.size()); + assertThat(mDatabaseManager.mMetadataCache).isEmpty(); assertThat(mTestDevice).isNotNull(); assertThat(mTestDevice2).isNotNull(); assertThat(mDatabaseManager.getMostRecentlyActiveHfpDevice()).isNull(); @@ -535,9 +532,8 @@ public final class DatabaseManagerTest { .isTrue(); List<BluetoothDevice> mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyActiveHfpDevice()); - Assert.assertEquals(1, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0)); + assertThat(mDatabaseManager.getMostRecentlyActiveHfpDevice()).isEqualTo(mTestDevice); + assertThat(mostRecentlyConnectedDevicesOrdered).containsExactly(mTestDevice); // Setting the second device's connection mDatabaseManager.setConnection(mTestDevice2, BluetoothProfile.HEADSET); @@ -547,11 +543,11 @@ public final class DatabaseManagerTest { .isFalse(); assertThat(mDatabaseManager.mMetadataCache.get(mTestDevice2.getAddress()).isActiveHfpDevice) .isTrue(); - Assert.assertEquals(mTestDevice2, mDatabaseManager.getMostRecentlyActiveHfpDevice()); + assertThat(mDatabaseManager.getMostRecentlyActiveHfpDevice()).isEqualTo(mTestDevice2); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice2, mTestDevice) + .inOrder(); // Disconnect first test device's connection mDatabaseManager.setDisconnection(mTestDevice, BluetoothProfile.HEADSET); @@ -561,9 +557,9 @@ public final class DatabaseManagerTest { .isFalse(); assertThat(mDatabaseManager.getMostRecentlyActiveHfpDevice()).isNotNull(); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(0)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice2, mTestDevice) + .inOrder(); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); @@ -575,7 +571,7 @@ public final class DatabaseManagerTest { public void testSetConnection() { mSetFlagsRule.disableFlags(Flags.FLAG_AUTO_CONNECT_ON_MULTIPLE_HFP_WHEN_NO_A2DP_DEVICE); // Verify pre-conditions to ensure a fresh test - Assert.assertEquals(0, mDatabaseManager.mMetadataCache.size()); + assertThat(mDatabaseManager.mMetadataCache).isEmpty(); assertThat(mTestDevice).isNotNull(); assertThat(mTestDevice2).isNotNull(); assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isNull(); @@ -590,9 +586,8 @@ public final class DatabaseManagerTest { .isTrue(); List<BluetoothDevice> mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice()); - Assert.assertEquals(1, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0)); + assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isEqualTo(mTestDevice); + assertThat(mostRecentlyConnectedDevicesOrdered).containsExactly(mTestDevice); // Setting the second device's connection mDatabaseManager.setConnection(mTestDevice2, BluetoothProfile.A2DP); @@ -606,11 +601,11 @@ public final class DatabaseManagerTest { mDatabaseManager.mMetadataCache.get(mTestDevice2.getAddress()) .is_active_a2dp_device) .isTrue(); - Assert.assertEquals(mTestDevice2, mDatabaseManager.getMostRecentlyConnectedA2dpDevice()); + assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isEqualTo(mTestDevice2); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice2, mTestDevice) + .inOrder(); // Connect first test device again mDatabaseManager.setConnection(mTestDevice, BluetoothProfile.A2DP); @@ -624,11 +619,11 @@ public final class DatabaseManagerTest { mDatabaseManager.mMetadataCache.get(mTestDevice2.getAddress()) .is_active_a2dp_device) .isFalse(); - Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice()); + assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isEqualTo(mTestDevice); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(1)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice, mTestDevice2) + .inOrder(); // Disconnect first test device's connection mDatabaseManager.setDisconnection(mTestDevice, BluetoothProfile.A2DP); @@ -644,9 +639,9 @@ public final class DatabaseManagerTest { .isFalse(); assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isNull(); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(2, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(1)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice, mTestDevice2) + .inOrder(); // Connect third test device (non-a2dp device) mDatabaseManager.setConnection(mTestDevice3, BluetoothProfile.HEADSET); @@ -666,10 +661,9 @@ public final class DatabaseManagerTest { .isFalse(); assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isNull(); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice3, mTestDevice, mTestDevice2) + .inOrder(); // Connect first test device again mDatabaseManager.setConnection(mTestDevice, BluetoothProfile.A2DP); @@ -687,12 +681,11 @@ public final class DatabaseManagerTest { mDatabaseManager.mMetadataCache.get(mTestDevice3.getAddress()) .is_active_a2dp_device) .isFalse(); - Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice()); + assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isEqualTo(mTestDevice); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice, mTestDevice3, mTestDevice2) + .inOrder(); // Connect third test device again and ensure it doesn't reset active a2dp device mDatabaseManager.setConnection(mTestDevice3, BluetoothProfile.HEADSET); @@ -710,12 +703,11 @@ public final class DatabaseManagerTest { mDatabaseManager.mMetadataCache.get(mTestDevice3.getAddress()) .is_active_a2dp_device) .isFalse(); - Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice()); + assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isEqualTo(mTestDevice); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice3, mTestDevice, mTestDevice2) + .inOrder(); // Disconnect second test device mDatabaseManager.setDisconnection(mTestDevice2, BluetoothProfile.A2DP); @@ -733,12 +725,11 @@ public final class DatabaseManagerTest { mDatabaseManager.mMetadataCache.get(mTestDevice3.getAddress()) .is_active_a2dp_device) .isFalse(); - Assert.assertEquals(mTestDevice, mDatabaseManager.getMostRecentlyConnectedA2dpDevice()); + assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isEqualTo(mTestDevice); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice3, mTestDevice, mTestDevice2) + .inOrder(); // Disconnect first test device mDatabaseManager.setDisconnection(mTestDevice, BluetoothProfile.A2DP); @@ -758,10 +749,9 @@ public final class DatabaseManagerTest { .isFalse(); assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isNull(); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice3, mTestDevice, mTestDevice2) + .inOrder(); // Disconnect third test device mDatabaseManager.setDisconnection(mTestDevice3, BluetoothProfile.A2DP); @@ -781,10 +771,9 @@ public final class DatabaseManagerTest { .isFalse(); assertThat(mDatabaseManager.getMostRecentlyConnectedA2dpDevice()).isNull(); mostRecentlyConnectedDevicesOrdered = mDatabaseManager.getMostRecentlyConnectedDevices(); - Assert.assertEquals(3, mostRecentlyConnectedDevicesOrdered.size()); - Assert.assertEquals(mTestDevice3, mostRecentlyConnectedDevicesOrdered.get(0)); - Assert.assertEquals(mTestDevice, mostRecentlyConnectedDevicesOrdered.get(1)); - Assert.assertEquals(mTestDevice2, mostRecentlyConnectedDevicesOrdered.get(2)); + assertThat(mostRecentlyConnectedDevicesOrdered) + .containsExactly(mTestDevice3, mTestDevice, mTestDevice2) + .inOrder(); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); @@ -1651,13 +1640,14 @@ public final class DatabaseManagerTest { mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data); mDatabase.insert(data); } - Assert.assertEquals( - expectedSetResult, - mDatabaseManager.setProfileConnectionPolicy( - mTestDevice, BluetoothProfile.HEADSET, connectionPolicy)); - Assert.assertEquals( - expectedConnectionPolicy, - mDatabaseManager.getProfileConnectionPolicy(mTestDevice, BluetoothProfile.HEADSET)); + assertThat( + mDatabaseManager.setProfileConnectionPolicy( + mTestDevice, BluetoothProfile.HEADSET, connectionPolicy)) + .isEqualTo(expectedSetResult); + assertThat( + mDatabaseManager.getProfileConnectionPolicy( + mTestDevice, BluetoothProfile.HEADSET)) + .isEqualTo(expectedConnectionPolicy); // Wait for database update TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper()); @@ -1668,17 +1658,18 @@ public final class DatabaseManagerTest { if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { // Database won't be updated - Assert.assertEquals(0, list.size()); + assertThat(list).isEmpty(); return; } } - Assert.assertEquals(1, list.size()); + assertThat(list.size()).isEqualTo(1); // Check whether the device is in database restartDatabaseManagerHelper(); - Assert.assertEquals( - expectedConnectionPolicy, - mDatabaseManager.getProfileConnectionPolicy(mTestDevice, BluetoothProfile.HEADSET)); + assertThat( + mDatabaseManager.getProfileConnectionPolicy( + mTestDevice, BluetoothProfile.HEADSET)) + .isEqualTo(expectedConnectionPolicy); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); @@ -1694,12 +1685,12 @@ public final class DatabaseManagerTest { } if (test == A2DP_SUPPORT_OP_CODEC_TEST) { mDatabaseManager.setA2dpSupportsOptionalCodecs(mTestDevice, value); - Assert.assertEquals( - expectedValue, mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice)); + assertThat(mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice)) + .isEqualTo(expectedValue); } else { mDatabaseManager.setA2dpOptionalCodecsEnabled(mTestDevice, value); - Assert.assertEquals( - expectedValue, mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice)); + assertThat(mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice)) + .isEqualTo(expectedValue); } // Wait for database update TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper()); @@ -1709,19 +1700,19 @@ public final class DatabaseManagerTest { // Check number of metadata in the database if (!stored) { // Database won't be updated - Assert.assertEquals(0, list.size()); + assertThat(list).isEmpty(); return; } - Assert.assertEquals(1, list.size()); + assertThat(list.size()).isEqualTo(1); // Check whether the device is in database restartDatabaseManagerHelper(); if (test == A2DP_SUPPORT_OP_CODEC_TEST) { - Assert.assertEquals( - expectedValue, mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice)); + assertThat(mDatabaseManager.getA2dpSupportsOptionalCodecs(mTestDevice)) + .isEqualTo(expectedValue); } else { - Assert.assertEquals( - expectedValue, mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice)); + assertThat(mDatabaseManager.getA2dpOptionalCodecsEnabled(mTestDevice)) + .isEqualTo(expectedValue); } mDatabaseManager.factoryReset(); @@ -1737,17 +1728,17 @@ public final class DatabaseManagerTest { Metadata data = new Metadata(TEST_BT_ADDR); mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data); mDatabase.insert(data); - Assert.assertEquals( - expectedResult, mDatabaseManager.setCustomMeta(mTestDevice, key, testValue)); + assertThat(mDatabaseManager.setCustomMeta(mTestDevice, key, testValue)) + .isEqualTo(expectedResult); verify(mAdapterService).onMetadataChanged(mTestDevice, key, testValue); verifyTime++; } - Assert.assertEquals( - expectedResult, mDatabaseManager.setCustomMeta(mTestDevice, key, value)); + assertThat(mDatabaseManager.setCustomMeta(mTestDevice, key, value)) + .isEqualTo(expectedResult); if (expectedResult) { // Check for callback and get value verify(mAdapterService, times(verifyTime)).onMetadataChanged(mTestDevice, key, value); - Assert.assertEquals(value, mDatabaseManager.getCustomMeta(mTestDevice, key)); + assertThat(mDatabaseManager.getCustomMeta(mTestDevice, key)).isEqualTo(value); } else { assertThat(mDatabaseManager.getCustomMeta(mTestDevice, key)).isNull(); return; @@ -1772,15 +1763,14 @@ public final class DatabaseManagerTest { Metadata data = new Metadata(TEST_BT_ADDR); mDatabaseManager.mMetadataCache.put(TEST_BT_ADDR, data); mDatabase.insert(data); - Assert.assertEquals( - expectedResult, - mDatabaseManager.setAudioPolicyMetadata(mTestDevice, testPolicy)); + assertThat(mDatabaseManager.setAudioPolicyMetadata(mTestDevice, testPolicy)) + .isEqualTo(expectedResult); } - Assert.assertEquals( - expectedResult, mDatabaseManager.setAudioPolicyMetadata(mTestDevice, policy)); + assertThat(mDatabaseManager.setAudioPolicyMetadata(mTestDevice, policy)) + .isEqualTo(expectedResult); if (expectedResult) { // Check for callback and get value - Assert.assertEquals(policy, mDatabaseManager.getAudioPolicyMetadata(mTestDevice)); + assertThat(mDatabaseManager.getAudioPolicyMetadata(mTestDevice)).isEqualTo(policy); } else { assertThat(mDatabaseManager.getAudioPolicyMetadata(mTestDevice)).isNull(); return; @@ -1790,7 +1780,7 @@ public final class DatabaseManagerTest { // Check whether the value is saved in database restartDatabaseManagerHelper(); - Assert.assertEquals(policy, mDatabaseManager.getAudioPolicyMetadata(mTestDevice)); + assertThat(mDatabaseManager.getAudioPolicyMetadata(mTestDevice)).isEqualTo(policy); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); @@ -1815,23 +1805,20 @@ public final class DatabaseManagerTest { groupDevices.add(mTestDevice); groupDevices.add(mTestDevice2); - Assert.assertEquals( - expectedSetResult, - mDatabaseManager.setPreferredAudioProfiles(groupDevices, preferencesToSet)); + assertThat(mDatabaseManager.setPreferredAudioProfiles(groupDevices, preferencesToSet)) + .isEqualTo(expectedSetResult); Bundle testDevicePreferences = mDatabaseManager.getPreferredAudioProfiles(mTestDevice); Bundle testDevice2Preferences = mDatabaseManager.getPreferredAudioProfiles(mTestDevice2); assertThat(testDevicePreferences).isNotNull(); assertThat(testDevice2Preferences).isNotNull(); - Assert.assertEquals( - expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY), - testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)); - Assert.assertEquals( - expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX), - testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)); - Assert.assertEquals( - 0, testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)); - Assert.assertEquals(0, testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)); + assertThat(testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)) + .isEqualTo(expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)); + assertThat(testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)) + .isEqualTo(expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)); + assertThat(testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)) + .isEqualTo(0); + assertThat(testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)).isEqualTo(0); // Wait for database update TestUtils.waitForLooperToFinishScheduledTask(mDatabaseManager.getHandlerLooper()); @@ -1840,10 +1827,10 @@ public final class DatabaseManagerTest { // Check number of metadata in the database if (!stored) { - Assert.assertEquals(0, list.size()); + assertThat(list).isEmpty(); return; } - Assert.assertEquals(2, list.size()); + assertThat(list.size()).isEqualTo(2); // Check whether the device is in database restartDatabaseManagerHelper(); @@ -1852,15 +1839,13 @@ public final class DatabaseManagerTest { assertThat(testDevicePreferences).isNotNull(); assertThat(testDevice2Preferences).isNotNull(); - Assert.assertEquals( - expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY), - testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)); - Assert.assertEquals( - expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX), - testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)); - Assert.assertEquals( - 0, testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)); - Assert.assertEquals(0, testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)); + assertThat(testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)) + .isEqualTo(expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)); + assertThat(testDevicePreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)) + .isEqualTo(expectedPreferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)); + assertThat(testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY)) + .isEqualTo(0); + assertThat(testDevice2Preferences.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX)).isEqualTo(0); mDatabaseManager.factoryReset(); mDatabaseManager.mMetadataCache.clear(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java index 8502c240d1..a2b46c9aa2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java @@ -43,7 +43,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; -import org.hamcrest.core.IsInstanceOf; import org.junit.*; import org.junit.Rule; import org.junit.runner.RunWith; @@ -112,7 +111,7 @@ public class CsipSetCoordinatorStateMachineTest { /** Test that default state is disconnected */ @Test public void testDefaultDisconnectedState() { - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } /** @@ -140,9 +139,8 @@ public class CsipSetCoordinatorStateMachineTest { // Verify that no connection state broadcast is executed verify(mService, after(TIMEOUT_MS).never()).sendBroadcast(any(Intent.class), anyString()); // Check that we are in Disconnected state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Disconnected.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Disconnected.class); } /** Test that an incoming connection with policy allowing connection is accepted */ @@ -162,14 +160,11 @@ public class CsipSetCoordinatorStateMachineTest { ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mService, timeout(TIMEOUT_MS).times(1)) .sendBroadcast(intentArgument1.capture(), anyString()); - Assert.assertEquals( - STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(STATE_CONNECTING); - // Check that we are in Connecting state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Connecting.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Connecting.class); // Send a message to trigger connection completed CsipSetCoordinatorStackEvent connCompletedEvent = @@ -185,10 +180,9 @@ public class CsipSetCoordinatorStateMachineTest { ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mService, timeout(TIMEOUT_MS).times(2)) .sendBroadcast(intentArgument2.capture(), anyString()); - // Check that we are in Connected state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Connected.class)); + + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Connected.class); } /** Test that an outgoing connection times out */ @@ -205,27 +199,21 @@ public class CsipSetCoordinatorStateMachineTest { ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mService, timeout(TIMEOUT_MS).times(1)) .sendBroadcast(intentArgument1.capture(), anyString()); - Assert.assertEquals( - STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(STATE_CONNECTING); - // Check that we are in Connecting state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Connecting.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Connecting.class); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mService, timeout(CsipSetCoordinatorStateMachine.sConnectTimeoutMs * 2L).times(2)) .sendBroadcast(intentArgument2.capture(), anyString()); - Assert.assertEquals( - STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(STATE_DISCONNECTED); - // Check that we are in Disconnected state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Disconnected.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Disconnected.class); verify(mNativeInterface).disconnect(eq(mTestDevice)); } @@ -248,33 +236,27 @@ public class CsipSetCoordinatorStateMachineTest { ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class); verify(mService, timeout(TIMEOUT_MS).times(1)) .sendBroadcast(intentArgument1.capture(), anyString()); - Assert.assertEquals( - STATE_CONNECTING, - intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(STATE_CONNECTING); - // Check that we are in Connecting state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Connecting.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Connecting.class); // Verify that one connection state broadcast is executed ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class); verify(mService, timeout(CsipSetCoordinatorStateMachine.sConnectTimeoutMs * 2L).times(2)) .sendBroadcast(intentArgument2.capture(), anyString()); - Assert.assertEquals( - STATE_DISCONNECTED, - intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); + assertThat(intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1)) + .isEqualTo(STATE_DISCONNECTED); - // Check that we are in Disconnected state - Assert.assertThat( - mStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(CsipSetCoordinatorStateMachine.Disconnected.class)); + assertThat(mStateMachine.getCurrentState()) + .isInstanceOf(CsipSetCoordinatorStateMachine.Disconnected.class); verify(mNativeInterface).disconnect(eq(mTestDevice)); } @Test public void testGetDevice() { - Assert.assertEquals(mTestDevice, mStateMachine.getDevice()); + assertThat(mStateMachine.getDevice()).isEqualTo(mTestDevice); } @Test @@ -294,7 +276,7 @@ public class CsipSetCoordinatorStateMachineTest { public void testProcessDisconnectMessage_onDisconnectedState() { mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.DISCONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } @Test @@ -302,12 +284,12 @@ public class CsipSetCoordinatorStateMachineTest { allowConnection(false); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.CONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); allowConnection(false); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.CONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); allowConnection(true); doReturn(true).when(mNativeInterface).connect(any(BluetoothDevice.class)); @@ -323,7 +305,7 @@ public class CsipSetCoordinatorStateMachineTest { CsipSetCoordinatorStackEvent event = new CsipSetCoordinatorStackEvent(-1); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); event = new CsipSetCoordinatorStackEvent( @@ -331,7 +313,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_DISCONNECTED; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); event = new CsipSetCoordinatorStackEvent( @@ -339,7 +321,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_CONNECTING; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); verify(mNativeInterface).disconnect(mTestDevice); Mockito.clearInvocations(mNativeInterface); @@ -349,7 +331,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_CONNECTED; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); verify(mNativeInterface).disconnect(mTestDevice); event = @@ -358,7 +340,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_DISCONNECTING; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); event = new CsipSetCoordinatorStackEvent( @@ -366,7 +348,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = -1; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED); } @Test @@ -424,7 +406,7 @@ public class CsipSetCoordinatorStateMachineTest { CsipSetCoordinatorStackEvent event = new CsipSetCoordinatorStackEvent(-1); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_CONNECTING, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTING); event = new CsipSetCoordinatorStackEvent( @@ -432,7 +414,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_CONNECTING; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_CONNECTING, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTING); event = new CsipSetCoordinatorStackEvent( @@ -440,7 +422,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = 10000; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_CONNECTING, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTING); } @Test @@ -484,7 +466,7 @@ public class CsipSetCoordinatorStateMachineTest { initToConnectedState(); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.CONNECT); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_CONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED); } @Test @@ -511,7 +493,7 @@ public class CsipSetCoordinatorStateMachineTest { CsipSetCoordinatorStackEvent event = new CsipSetCoordinatorStackEvent(-1); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_CONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED); event = new CsipSetCoordinatorStackEvent( @@ -519,7 +501,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_CONNECTING; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_CONNECTED, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED); } @Test @@ -577,7 +559,7 @@ public class CsipSetCoordinatorStateMachineTest { CsipSetCoordinatorStackEvent event = new CsipSetCoordinatorStackEvent(-1); mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTING, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTING); allowConnection(false); event = @@ -603,7 +585,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = CsipSetCoordinatorStackEvent.CONNECTION_STATE_DISCONNECTING; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTING, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTING); event = new CsipSetCoordinatorStackEvent( @@ -611,7 +593,7 @@ public class CsipSetCoordinatorStateMachineTest { event.valueInt1 = 10000; mStateMachine.sendMessage(CsipSetCoordinatorStateMachine.STACK_EVENT, event); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertEquals(STATE_DISCONNECTING, mStateMachine.getConnectionState()); + assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTING); } @Test @@ -706,7 +688,7 @@ public class CsipSetCoordinatorStateMachineTest { mStateMachine.sendMessage(msg); // Verify that one connection state broadcast is executed verify(mService, timeout(TIMEOUT_MS)).sendBroadcast(any(Intent.class), anyString()); - Assert.assertThat(mStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type)); + assertThat(mStateMachine.getCurrentState()).isInstanceOf(type); } public static class CsipSetCoordinatorStateMachineWrapper diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java new file mode 100644 index 0000000000..3a0abb2870 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java @@ -0,0 +1,188 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.gatt; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertisingSetParameters; +import android.bluetooth.le.IAdvertisingSetCallback; +import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.AttributionSource; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.bluetooth.btservice.AdapterService; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** Test cases for {@link AdvertiseBinder}. */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class AdvertiseBinderTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock private AdapterService mAdapterService; + @Mock private AdvertiseManager mAdvertiseManager; + + private final AttributionSource mAttributionSource = + BluetoothAdapter.getDefaultAdapter().getAttributionSource(); + private AdvertiseBinder mBinder; + + @Before + public void setUp() { + mBinder = new AdvertiseBinder(mAdapterService, mAdvertiseManager); + } + + @Test + public void startAdvertisingSet() { + AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); + AdvertiseData advertiseData = new AdvertiseData.Builder().build(); + AdvertiseData scanResponse = new AdvertiseData.Builder().build(); + PeriodicAdvertisingParameters periodicParameters = + new PeriodicAdvertisingParameters.Builder().build(); + AdvertiseData periodicData = new AdvertiseData.Builder().build(); + int duration = 1; + int maxExtAdvEvents = 2; + int serverIf = 3; + IAdvertisingSetCallback callback = mock(IAdvertisingSetCallback.class); + + mBinder.startAdvertisingSet( + parameters, + advertiseData, + scanResponse, + periodicParameters, + periodicData, + duration, + maxExtAdvEvents, + serverIf, + callback, + mAttributionSource); + + verify(mAdvertiseManager) + .startAdvertisingSet( + parameters, + advertiseData, + scanResponse, + periodicParameters, + periodicData, + duration, + maxExtAdvEvents, + serverIf, + callback, + mAttributionSource); + } + + @Test + public void stopAdvertisingSet() { + IAdvertisingSetCallback callback = mock(IAdvertisingSetCallback.class); + + mBinder.stopAdvertisingSet(callback, mAttributionSource); + + verify(mAdvertiseManager).stopAdvertisingSet(callback); + } + + @Test + public void setAdvertisingData() { + int advertiserId = 1; + AdvertiseData data = new AdvertiseData.Builder().build(); + + mBinder.setAdvertisingData(advertiserId, data, mAttributionSource); + verify(mAdvertiseManager).setAdvertisingData(advertiserId, data); + } + + @Test + public void setAdvertisingParameters() { + int advertiserId = 1; + AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); + + mBinder.setAdvertisingParameters(advertiserId, parameters, mAttributionSource); + verify(mAdvertiseManager).setAdvertisingParameters(advertiserId, parameters); + } + + @Test + public void setPeriodicAdvertisingData() { + int advertiserId = 1; + AdvertiseData data = new AdvertiseData.Builder().build(); + + mBinder.setPeriodicAdvertisingData(advertiserId, data, mAttributionSource); + verify(mAdvertiseManager).setPeriodicAdvertisingData(advertiserId, data); + } + + @Test + public void setPeriodicAdvertisingEnable() { + int advertiserId = 1; + boolean enable = true; + + mBinder.setPeriodicAdvertisingEnable(advertiserId, enable, mAttributionSource); + verify(mAdvertiseManager).setPeriodicAdvertisingEnable(advertiserId, enable); + } + + @Test + public void setPeriodicAdvertisingParameters() { + int advertiserId = 1; + PeriodicAdvertisingParameters parameters = + new PeriodicAdvertisingParameters.Builder().build(); + + mBinder.setPeriodicAdvertisingParameters(advertiserId, parameters, mAttributionSource); + verify(mAdvertiseManager).setPeriodicAdvertisingParameters(advertiserId, parameters); + } + + @Test + public void setScanResponseData() { + int advertiserId = 1; + AdvertiseData data = new AdvertiseData.Builder().build(); + + mBinder.setScanResponseData(advertiserId, data, mAttributionSource); + verify(mAdvertiseManager).setScanResponseData(advertiserId, data); + } + + @Test + public void getOwnAddress() { + int advertiserId = 1; + + mBinder.getOwnAddress(advertiserId, mAttributionSource); + verify(mAdvertiseManager).getOwnAddress(advertiserId); + } + + @Test + public void enableAdvertisingSet() { + int advertiserId = 1; + boolean enable = true; + int duration = 3; + int maxExtAdvEvents = 4; + + mBinder.enableAdvertisingSet( + advertiserId, enable, duration, maxExtAdvEvents, mAttributionSource); + verify(mAdvertiseManager) + .enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); + } + + @Test + public void cleanUp_doesNotCrash() { + mBinder.cleanup(); + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java index cb3aa0dc88..93a783fc7c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java @@ -102,7 +102,7 @@ public class AppAdvertiseStatsTest { AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name, mAttributionSource); - assertThat(appAdvertiseStats.mAdvertiserRecords.size()).isEqualTo(0); + assertThat(appAdvertiseStats.mAdvertiserRecords).isEmpty(); int duration = 1; int maxExtAdvEvents = 2; @@ -145,7 +145,7 @@ public class AppAdvertiseStatsTest { int maxExtAdvEvents = 2; int instanceCount = 3; - assertThat(appAdvertiseStats.mAdvertiserRecords.size()).isEqualTo(0); + assertThat(appAdvertiseStats.mAdvertiserRecords).isEmpty(); appAdvertiseStats.recordAdvertiseStart(duration, maxExtAdvEvents, instanceCount); @@ -186,7 +186,7 @@ public class AppAdvertiseStatsTest { int maxExtAdvEvents = 2; int instanceCount = 3; - assertThat(appAdvertiseStats.mAdvertiserRecords.size()).isEqualTo(0); + assertThat(appAdvertiseStats.mAdvertiserRecords).isEmpty(); appAdvertiseStats.enableAdvertisingSet(true, duration, maxExtAdvEvents, instanceCount); appAdvertiseStats.enableAdvertisingSet(false, duration, maxExtAdvEvents, instanceCount); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java new file mode 100644 index 0000000000..3ed9b80092 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.gatt; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.DistanceMeasurementMethod; +import android.bluetooth.le.DistanceMeasurementParams; +import android.bluetooth.le.IDistanceMeasurementCallback; +import android.content.AttributionSource; +import android.os.ParcelUuid; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.bluetooth.btservice.AdapterService; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.UUID; + +/** Test cases for {@link DistanceMeasurementBinder}. */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class DistanceMeasurementBinderTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock private DistanceMeasurementManager mDistanceMeasurementManager; + @Mock private AdapterService mAdapterService; + + private final AttributionSource mAttributionSource = + BluetoothAdapter.getDefaultAdapter().getAttributionSource(); + + private DistanceMeasurementBinder mBinder; + + @Before + public void setUp() { + mBinder = new DistanceMeasurementBinder(mAdapterService, mDistanceMeasurementManager); + when(mDistanceMeasurementManager.getSupportedDistanceMeasurementMethods()) + .thenReturn(new DistanceMeasurementMethod[0]); + } + + @Test + public void getSupportedDistanceMeasurementMethods() { + mBinder.getSupportedDistanceMeasurementMethods(mAttributionSource); + verify(mDistanceMeasurementManager).getSupportedDistanceMeasurementMethods(); + } + + @Test + public void startDistanceMeasurement() { + UUID uuid = UUID.randomUUID(); + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter().getRemoteDevice("00:01:02:03:04:05"); + DistanceMeasurementParams params = + new DistanceMeasurementParams.Builder(device) + .setDurationSeconds(123) + .setFrequency(DistanceMeasurementParams.REPORT_FREQUENCY_LOW) + .build(); + IDistanceMeasurementCallback callback = mock(IDistanceMeasurementCallback.class); + mBinder.startDistanceMeasurement( + new ParcelUuid(uuid), params, callback, mAttributionSource); + verify(mDistanceMeasurementManager).startDistanceMeasurement(uuid, params, callback); + } + + @Test + public void stopDistanceMeasurement() { + UUID uuid = UUID.randomUUID(); + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter().getRemoteDevice("00:01:02:03:04:05"); + int method = DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI; + mBinder.stopDistanceMeasurement(new ParcelUuid(uuid), device, method, mAttributionSource); + verify(mDistanceMeasurementManager).stopDistanceMeasurement(uuid, device, method, false); + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java index 0e5bfaac94..24457ebe6a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java @@ -25,10 +25,6 @@ import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; -import android.bluetooth.le.AdvertiseData; -import android.bluetooth.le.AdvertisingSetParameters; -import android.bluetooth.le.IAdvertisingSetCallback; -import android.bluetooth.le.PeriodicAdvertisingParameters; import android.content.AttributionSource; import android.os.ParcelUuid; @@ -515,140 +511,6 @@ public class GattServiceBinderTest { } @Test - public void startAdvertisingSet() throws Exception { - AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); - AdvertiseData advertiseData = new AdvertiseData.Builder().build(); - AdvertiseData scanResponse = new AdvertiseData.Builder().build(); - PeriodicAdvertisingParameters periodicParameters = - new PeriodicAdvertisingParameters.Builder().build(); - AdvertiseData periodicData = new AdvertiseData.Builder().build(); - int duration = 1; - int maxExtAdvEvents = 2; - int serverIf = 3; - IAdvertisingSetCallback callback = mock(IAdvertisingSetCallback.class); - - mBinder.startAdvertisingSet( - parameters, - advertiseData, - scanResponse, - periodicParameters, - periodicData, - duration, - maxExtAdvEvents, - serverIf, - callback, - mAttributionSource); - - verify(mService) - .startAdvertisingSet( - parameters, - advertiseData, - scanResponse, - periodicParameters, - periodicData, - duration, - maxExtAdvEvents, - serverIf, - callback, - mAttributionSource); - } - - @Test - public void stopAdvertisingSet() throws Exception { - IAdvertisingSetCallback callback = mock(IAdvertisingSetCallback.class); - - mBinder.stopAdvertisingSet(callback, mAttributionSource); - - verify(mService).stopAdvertisingSet(callback, mAttributionSource); - } - - @Test - public void getOwnAddress() throws Exception { - int advertiserId = 1; - - mBinder.getOwnAddress(advertiserId, mAttributionSource); - - verify(mService).getOwnAddress(advertiserId, mAttributionSource); - } - - @Test - public void enableAdvertisingSet() throws Exception { - int advertiserId = 1; - boolean enable = true; - int duration = 3; - int maxExtAdvEvents = 4; - - mBinder.enableAdvertisingSet( - advertiserId, enable, duration, maxExtAdvEvents, mAttributionSource); - - verify(mService) - .enableAdvertisingSet( - advertiserId, enable, duration, maxExtAdvEvents, mAttributionSource); - } - - @Test - public void setAdvertisingData() throws Exception { - int advertiserId = 1; - AdvertiseData data = new AdvertiseData.Builder().build(); - - mBinder.setAdvertisingData(advertiserId, data, mAttributionSource); - - verify(mService).setAdvertisingData(advertiserId, data, mAttributionSource); - } - - @Test - public void setScanResponseData() throws Exception { - int advertiserId = 1; - AdvertiseData data = new AdvertiseData.Builder().build(); - - mBinder.setScanResponseData(advertiserId, data, mAttributionSource); - - verify(mService).setScanResponseData(advertiserId, data, mAttributionSource); - } - - @Test - public void setAdvertisingParameters() throws Exception { - int advertiserId = 1; - AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); - - mBinder.setAdvertisingParameters(advertiserId, parameters, mAttributionSource); - - verify(mService).setAdvertisingParameters(advertiserId, parameters, mAttributionSource); - } - - @Test - public void setPeriodicAdvertisingParameters() throws Exception { - int advertiserId = 1; - PeriodicAdvertisingParameters parameters = - new PeriodicAdvertisingParameters.Builder().build(); - - mBinder.setPeriodicAdvertisingParameters(advertiserId, parameters, mAttributionSource); - - verify(mService) - .setPeriodicAdvertisingParameters(advertiserId, parameters, mAttributionSource); - } - - @Test - public void setPeriodicAdvertisingData() throws Exception { - int advertiserId = 1; - AdvertiseData data = new AdvertiseData.Builder().build(); - - mBinder.setPeriodicAdvertisingData(advertiserId, data, mAttributionSource); - - verify(mService).setPeriodicAdvertisingData(advertiserId, data, mAttributionSource); - } - - @Test - public void setPeriodicAdvertisingEnable() throws Exception { - int advertiserId = 1; - boolean enable = true; - - mBinder.setPeriodicAdvertisingEnable(advertiserId, enable, mAttributionSource); - - verify(mService).setPeriodicAdvertisingEnable(advertiserId, enable, mAttributionSource); - } - - @Test public void disconnectAll() throws Exception { mBinder.disconnectAll(mAttributionSource); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java index 04a46a96b3..f9d12f1991 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java @@ -30,12 +30,6 @@ import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; -import android.bluetooth.le.AdvertiseData; -import android.bluetooth.le.AdvertisingSetParameters; -import android.bluetooth.le.DistanceMeasurementMethod; -import android.bluetooth.le.DistanceMeasurementParams; -import android.bluetooth.le.IDistanceMeasurementCallback; -import android.bluetooth.le.PeriodicAdvertisingParameters; import android.companion.CompanionDeviceManager; import android.content.AttributionSource; import android.content.Context; @@ -55,6 +49,7 @@ import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.CompanionManager; import com.android.bluetooth.flags.Flags; +import com.android.bluetooth.le_scan.PeriodicScanManager; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.le_scan.ScanObjectsFactory; @@ -84,6 +79,7 @@ public class GattServiceTest { @Mock private ContextMap<IBluetoothGattCallback> mClientMap; @Mock private ScanManager mScanManager; + @Mock private PeriodicScanManager mPeriodicScanManager; @Mock private Set<String> mReliableQueue; @Mock private ContextMap<IBluetoothGattServerCallback> mServerMap; @Mock private DistanceMeasurementManager mDistanceMeasurementManager; @@ -130,6 +126,7 @@ public class GattServiceTest { doReturn(mScanManager) .when(mScanObjectsFactory) .createScanManager(any(), any(), any(), any()); + doReturn(mPeriodicScanManager).when(mScanObjectsFactory).createPeriodicScanManager(any()); doReturn(mContext.getPackageManager()).when(mAdapterService).getPackageManager(); doReturn(mContext.getSharedPreferences("GattServiceTestPrefs", Context.MODE_PRIVATE)) .when(mAdapterService) @@ -286,55 +283,6 @@ public class GattServiceTest { } @Test - public void setAdvertisingData() { - int advertiserId = 1; - AdvertiseData data = new AdvertiseData.Builder().build(); - - mService.setAdvertisingData(advertiserId, data, mAttributionSource); - } - - @Test - public void setAdvertisingParameters() { - int advertiserId = 1; - AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build(); - - mService.setAdvertisingParameters(advertiserId, parameters, mAttributionSource); - } - - @Test - public void setPeriodicAdvertisingData() { - int advertiserId = 1; - AdvertiseData data = new AdvertiseData.Builder().build(); - - mService.setPeriodicAdvertisingData(advertiserId, data, mAttributionSource); - } - - @Test - public void setPeriodicAdvertisingEnable() { - int advertiserId = 1; - boolean enable = true; - - mService.setPeriodicAdvertisingEnable(advertiserId, enable, mAttributionSource); - } - - @Test - public void setPeriodicAdvertisingParameters() { - int advertiserId = 1; - PeriodicAdvertisingParameters parameters = - new PeriodicAdvertisingParameters.Builder().build(); - - mService.setPeriodicAdvertisingParameters(advertiserId, parameters, mAttributionSource); - } - - @Test - public void setScanResponseData() { - int advertiserId = 1; - AdvertiseData data = new AdvertiseData.Builder().build(); - - mService.setScanResponseData(advertiserId, data, mAttributionSource); - } - - @Test public void getDevicesMatchingConnectionStates() { int[] states = new int[] {BluetoothProfile.STATE_CONNECTED}; @@ -626,24 +574,6 @@ public class GattServiceTest { } @Test - public void getOwnAddress() throws Exception { - int advertiserId = 1; - - mService.getOwnAddress(advertiserId, mAttributionSource); - } - - @Test - public void enableAdvertisingSet() throws Exception { - int advertiserId = 1; - boolean enable = true; - int duration = 3; - int maxExtAdvEvents = 4; - - mService.enableAdvertisingSet( - advertiserId, enable, duration, maxExtAdvEvents, mAttributionSource); - } - - @Test public void unregAll() throws Exception { int appId = 1; List<Integer> appIds = new ArrayList<>(); @@ -656,35 +586,6 @@ public class GattServiceTest { } @Test - public void getSupportedDistanceMeasurementMethods() { - mService.getSupportedDistanceMeasurementMethods(); - verify(mDistanceMeasurementManager).getSupportedDistanceMeasurementMethods(); - } - - @Test - public void startDistanceMeasurement() { - UUID uuid = UUID.randomUUID(); - BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - DistanceMeasurementParams params = - new DistanceMeasurementParams.Builder(device) - .setDurationSeconds(123) - .setFrequency(DistanceMeasurementParams.REPORT_FREQUENCY_LOW) - .build(); - IDistanceMeasurementCallback callback = mock(IDistanceMeasurementCallback.class); - mService.startDistanceMeasurement(uuid, params, callback); - verify(mDistanceMeasurementManager).startDistanceMeasurement(uuid, params, callback); - } - - @Test - public void stopDistanceMeasurement() { - UUID uuid = UUID.randomUUID(); - BluetoothDevice device = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - int method = DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI; - mService.stopDistanceMeasurement(uuid, device, method); - verify(mDistanceMeasurementManager).stopDistanceMeasurement(uuid, device, method, false); - } - - @Test public void cleanUp_doesNotCrash() { mService.cleanup(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java index a1095a6c59..306263f3ab 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java @@ -58,7 +58,6 @@ import com.android.bluetooth.btservice.SilenceDeviceManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; -import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -71,8 +70,8 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Set; /** Tests for {@link HeadsetService} */ @@ -192,15 +191,13 @@ public class HeadsetServiceTest { /** Test to verify that HeadsetService can be successfully started */ @Test public void testGetHeadsetService() { - Assert.assertEquals(mHeadsetService, HeadsetService.getHeadsetService()); + assertThat(HeadsetService.getHeadsetService()).isEqualTo(mHeadsetService); // Verify default connection and audio states mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertEquals( - BluetoothHeadset.STATE_AUDIO_DISCONNECTED, - mHeadsetService.getAudioState(mCurrentDevice)); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetService.getAudioState(mCurrentDevice)) + .isEqualTo(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); } /** Test okToAcceptConnection method using various test cases */ @@ -300,16 +297,13 @@ public class HeadsetServiceTest { when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - mHeadsetService.getConnectionState(mCurrentDevice)); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertEquals( - Collections.singletonList(mCurrentDevice), mHeadsetService.getConnectedDevices()); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()).isEqualTo(List.of(mCurrentDevice)); // 2nd connection attempt will fail assertThat(mHeadsetService.connect(mCurrentDevice)).isFalse(); // Verify makeStateMachine is only called once @@ -346,11 +340,9 @@ public class HeadsetServiceTest { when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertEquals( - Collections.singletonList(mCurrentDevice), mHeadsetService.getConnectedDevices()); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()).isEqualTo(List.of(mCurrentDevice)); // Test disconnect from native HeadsetStackEvent disconnectEvent = new HeadsetStackEvent( @@ -362,10 +354,9 @@ public class HeadsetServiceTest { .sendMessage(HeadsetStateMachine.STACK_EVENT, disconnectEvent); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertEquals(Collections.EMPTY_LIST, mHeadsetService.getConnectedDevices()); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetService.getConnectedDevices()).isEmpty(); } /** @@ -450,20 +441,17 @@ public class HeadsetServiceTest { // Put device to connecting when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Put device to connected connectedDevices.add(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); } // Connect the next device will fail mCurrentDevice = TestUtils.getTestDevice(mAdapter, MAX_HEADSET_CONNECTIONS); @@ -477,12 +465,10 @@ public class HeadsetServiceTest { eq(mAdapterService), eq(mNativeInterface), eq(mSystemInterface)); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); } /** @@ -512,40 +498,37 @@ public class HeadsetServiceTest { .thenReturn(BluetoothProfile.STATE_CONNECTED); when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()) .thenReturn(SystemClock.uptimeMillis()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertEquals( - Collections.singletonList(mCurrentDevice), mHeadsetService.getConnectedDevices()); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()).isEqualTo(List.of(mCurrentDevice)); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED); // Test connect audio - set the device first as the active device assertThat(mHeadsetService.setActiveDevice(mCurrentDevice)).isTrue(); - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(mStateMachines.get(mCurrentDevice)) .sendMessage(HeadsetStateMachine.CONNECT_AUDIO, mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTING); // 2nd connection attempt for the same device will succeed as well - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); // Verify CONNECT_AUDIO is only sent once verify(mStateMachines.get(mCurrentDevice)) .sendMessage(eq(HeadsetStateMachine.CONNECT_AUDIO), any()); // Test disconnect audio - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.disconnectAudio(mCurrentDevice)); + assertThat(mHeadsetService.disconnectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(mStateMachines.get(mCurrentDevice)) .sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); // Further disconnection requests will fail - Assert.assertEquals( - BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED, - mHeadsetService.disconnectAudio(mCurrentDevice)); + assertThat(mHeadsetService.disconnectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED); verify(mStateMachines.get(mCurrentDevice)) .sendMessage(eq(HeadsetStateMachine.DISCONNECT_AUDIO), any(BluetoothDevice.class)); } @@ -590,9 +573,8 @@ public class HeadsetServiceTest { mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Put device to connected connectedDevices.add(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); @@ -600,33 +582,30 @@ public class HeadsetServiceTest { .thenReturn(BluetoothProfile.STATE_CONNECTED); when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()) .thenReturn(SystemClock.uptimeMillis()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Try to connect audio // Should fail - Assert.assertEquals( - BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE, - mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE); // Should succeed after setActiveDevice() assertThat(mHeadsetService.setActiveDevice(mCurrentDevice)).isTrue(); - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(mStateMachines.get(mCurrentDevice)) .sendMessage(HeadsetStateMachine.CONNECT_AUDIO, mCurrentDevice); // Put device to audio connecting state when(mStateMachines.get(mCurrentDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTING); // 2nd connection attempt will also succeed - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); // Verify CONNECT_AUDIO is only sent once verify(mStateMachines.get(mCurrentDevice)) .sendMessage(eq(HeadsetStateMachine.CONNECT_AUDIO), any()); @@ -634,16 +613,15 @@ public class HeadsetServiceTest { when(mStateMachines.get(mCurrentDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED); // Disconnect audio - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.disconnectAudio(mCurrentDevice)); + assertThat(mHeadsetService.disconnectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(mStateMachines.get(mCurrentDevice)) .sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED); // Further disconnection requests will fail - Assert.assertEquals( - BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED, - mHeadsetService.disconnectAudio(mCurrentDevice)); + assertThat(mHeadsetService.disconnectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED); verify(mStateMachines.get(mCurrentDevice)) .sendMessage( eq(HeadsetStateMachine.DISCONNECT_AUDIO), any(BluetoothDevice.class)); @@ -691,9 +669,8 @@ public class HeadsetServiceTest { mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Put device to connected connectedDevices.add(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); @@ -705,12 +682,10 @@ public class HeadsetServiceTest { mCurrentDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); } if (MAX_HEADSET_CONNECTIONS >= 2) { // Try to connect audio @@ -718,29 +693,27 @@ public class HeadsetServiceTest { BluetoothDevice secondDevice = connectedDevices.get(1); // Set the first device as the active device assertThat(mHeadsetService.setActiveDevice(firstDevice)).isTrue(); - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio(firstDevice)); + assertThat(mHeadsetService.connectAudio(firstDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(mStateMachines.get(firstDevice)) .sendMessage(HeadsetStateMachine.CONNECT_AUDIO, firstDevice); // Put device to audio connecting state when(mStateMachines.get(firstDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTING); // 2nd connection attempt will succeed for the same device - Assert.assertEquals( - BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio(firstDevice)); + assertThat(mHeadsetService.connectAudio(firstDevice)) + .isEqualTo(BluetoothStatusCodes.SUCCESS); // Connect to 2nd device will fail - Assert.assertEquals( - BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE, - mHeadsetService.connectAudio(secondDevice)); + assertThat(mHeadsetService.connectAudio(secondDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE); verify(mStateMachines.get(secondDevice), never()) .sendMessage(HeadsetStateMachine.CONNECT_AUDIO, secondDevice); // Put device to audio connected state when(mStateMachines.get(firstDevice).getAudioState()) .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED); // Connect to 2nd device will fail - Assert.assertEquals( - BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE, - mHeadsetService.connectAudio(secondDevice)); + assertThat(mHeadsetService.connectAudio(secondDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE); verify(mStateMachines.get(secondDevice), never()) .sendMessage(HeadsetStateMachine.CONNECT_AUDIO, secondDevice); } @@ -796,9 +769,8 @@ public class HeadsetServiceTest { mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Put device to connected connectedDevices.add(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); @@ -806,12 +778,10 @@ public class HeadsetServiceTest { .thenReturn(BluetoothProfile.STATE_CONNECTED); when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()) .thenReturn(SystemClock.uptimeMillis()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_CONNECTING, @@ -820,7 +790,7 @@ public class HeadsetServiceTest { // Try to connect audio BluetoothDevice firstDevice = connectedDevices.get(0); assertThat(mHeadsetService.setActiveDevice(firstDevice)).isTrue(); - Assert.assertEquals(BluetoothStatusCodes.SUCCESS, mHeadsetService.connectAudio()); + assertThat(mHeadsetService.connectAudio()).isEqualTo(BluetoothStatusCodes.SUCCESS); verify(mStateMachines.get(firstDevice)) .sendMessage(HeadsetStateMachine.CONNECT_AUDIO, firstDevice); } @@ -832,9 +802,8 @@ public class HeadsetServiceTest { @Test public void testConnectAudio_deviceNeverConnected() { mCurrentDevice = TestUtils.getTestDevice(mAdapter, 0); - Assert.assertEquals( - BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED, - mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED); } /** @@ -862,18 +831,16 @@ public class HeadsetServiceTest { // Put device in disconnected state when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertEquals(Collections.EMPTY_LIST, mHeadsetService.getConnectedDevices()); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetService.getConnectedDevices()).isEmpty(); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED); // connectAudio should fail - Assert.assertEquals( - BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE, - mHeadsetService.connectAudio(mCurrentDevice)); + assertThat(mHeadsetService.connectAudio(mCurrentDevice)) + .isEqualTo(BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE); verify(mStateMachines.get(mCurrentDevice), never()) .sendMessage(eq(HeadsetStateMachine.CONNECT_AUDIO), any()); } @@ -943,9 +910,8 @@ public class HeadsetServiceTest { mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Put device to connected connectedDevices.add(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); @@ -953,12 +919,10 @@ public class HeadsetServiceTest { .thenReturn(BluetoothProfile.STATE_CONNECTED); when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()) .thenReturn(SystemClock.uptimeMillis()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_CONNECTING, @@ -1055,9 +1019,8 @@ public class HeadsetServiceTest { mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); // Put device to connected connectedDevices.add(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); @@ -1065,12 +1028,10 @@ public class HeadsetServiceTest { .thenReturn(BluetoothProfile.STATE_CONNECTED); when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()) .thenReturn(SystemClock.uptimeMillis()); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); - Assert.assertThat( - mHeadsetService.getConnectedDevices(), - Matchers.containsInAnyOrder(connectedDevices.toArray())); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetService.getConnectedDevices()) + .containsExactlyElementsIn(connectedDevices); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_CONNECTING, @@ -1118,9 +1079,8 @@ public class HeadsetServiceTest { when(mStateMachines.get(mCurrentDevice).getDevice()).thenReturn(mCurrentDevice); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHeadsetService.getConnectionState(mCurrentDevice)); + assertThat(mHeadsetService.getConnectionState(mCurrentDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); mHeadsetService.clccResponse(1, 0, 0, 0, false, "8225319000", 0); // index 0 is the end mark of CLCC response. mHeadsetService.clccResponse(0, 0, 0, 0, false, "8225319000", 0); @@ -1185,23 +1145,23 @@ public class HeadsetServiceTest { // Test whether active device been removed after enable silence mode. assertThat(mHeadsetService.setActiveDevice(mCurrentDevice)).isTrue(); - Assert.assertEquals(mCurrentDevice, mHeadsetService.getActiveDevice()); + assertThat(mHeadsetService.getActiveDevice()).isEqualTo(mCurrentDevice); assertThat(mHeadsetService.setSilenceMode(mCurrentDevice, true)).isTrue(); assertThat(mHeadsetService.getActiveDevice()).isNull(); // Test whether active device been resumed after disable silence mode. assertThat(mHeadsetService.setSilenceMode(mCurrentDevice, false)).isTrue(); - Assert.assertEquals(mCurrentDevice, mHeadsetService.getActiveDevice()); + assertThat(mHeadsetService.getActiveDevice()).isEqualTo(mCurrentDevice); // Test that active device should not be changed when silence a non-active device assertThat(mHeadsetService.setActiveDevice(mCurrentDevice)).isTrue(); - Assert.assertEquals(mCurrentDevice, mHeadsetService.getActiveDevice()); + assertThat(mHeadsetService.getActiveDevice()).isEqualTo(mCurrentDevice); assertThat(mHeadsetService.setSilenceMode(otherDevice, true)).isTrue(); - Assert.assertEquals(mCurrentDevice, mHeadsetService.getActiveDevice()); + assertThat(mHeadsetService.getActiveDevice()).isEqualTo(mCurrentDevice); // Test that active device should not be changed when another device exits silence mode assertThat(mHeadsetService.setSilenceMode(otherDevice, false)).isTrue(); - Assert.assertEquals(mCurrentDevice, mHeadsetService.getActiveDevice()); + assertThat(mHeadsetService.getActiveDevice()).isEqualTo(mCurrentDevice); } /** Test that whether active device been removed after enable silence mode */ @@ -1224,7 +1184,7 @@ public class HeadsetServiceTest { // Test that active device should not be changed if audio is not allowed assertThat(mHeadsetService.setActiveDevice(mCurrentDevice)).isFalse(); - Assert.assertEquals(null, mHeadsetService.getActiveDevice()); + assertThat(mHeadsetService.getActiveDevice()).isNull(); } @Test @@ -1288,8 +1248,7 @@ public class HeadsetServiceTest { .thenReturn(BluetoothProfile.STATE_CONNECTED); when(mStateMachines.get(mCurrentDevice).getConnectingTimestampMs()) .thenReturn(SystemClock.uptimeMillis()); - Assert.assertEquals( - Collections.singletonList(mCurrentDevice), mHeadsetService.getConnectedDevices()); + assertThat(mHeadsetService.getConnectedDevices()).isEqualTo(List.of(mCurrentDevice)); mHeadsetService.onConnectionStateChangedFromStateMachine( mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED, @@ -1304,7 +1263,7 @@ public class HeadsetServiceTest { BluetoothSinkAudioPolicy.POLICY_ALLOWED) .setInBandRingtonePolicy(BluetoothSinkAudioPolicy.POLICY_ALLOWED) .build()); - Assert.assertEquals(true, mHeadsetService.isInbandRingingEnabled()); + assertThat(mHeadsetService.isInbandRingingEnabled()).isTrue(); when(mStateMachines.get(mCurrentDevice).getHfpCallAudioPolicy()) .thenReturn( @@ -1315,7 +1274,7 @@ public class HeadsetServiceTest { .setInBandRingtonePolicy( BluetoothSinkAudioPolicy.POLICY_NOT_ALLOWED) .build()); - Assert.assertEquals(false, mHeadsetService.isInbandRingingEnabled()); + assertThat(mHeadsetService.isInbandRingingEnabled()).isFalse(); } private void addConnectedDeviceHelper(BluetoothDevice device) { @@ -1327,12 +1286,12 @@ public class HeadsetServiceTest { when(mStateMachines.get(device).getDevice()).thenReturn(device); when(mStateMachines.get(device).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mHeadsetService.getConnectionState(device)); + assertThat(mHeadsetService.getConnectionState(device)) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); when(mStateMachines.get(mCurrentDevice).getConnectionState()) .thenReturn(BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mHeadsetService.getConnectionState(device)); + assertThat(mHeadsetService.getConnectionState(device)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); assertThat(mHeadsetService.getConnectedDevices()).contains(device); } @@ -1349,6 +1308,6 @@ public class HeadsetServiceTest { doReturn(bondState).when(mAdapterService).getBondState(device); when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HEADSET)) .thenReturn(priority); - Assert.assertEquals(expected, mHeadsetService.okToAcceptConnection(device, false)); + assertThat(mHeadsetService.okToAcceptConnection(device, false)).isEqualTo(expected); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java index 75dfc971a1..e594c924a8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java @@ -66,9 +66,7 @@ import com.android.bluetooth.btservice.SilenceDeviceManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; -import org.hamcrest.core.IsInstanceOf; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -186,22 +184,20 @@ public class HeadsetStateMachineTest { /** Test that default state is Disconnected */ @Test public void testDefaultDisconnectedState() { - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mHeadsetStateMachine.getConnectionState()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** Test that state is Connected after calling setUpConnectedState() */ @Test public void testSetupConnectedState() { setUpConnectedState(); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mHeadsetStateMachine.getConnectionState()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** Test state transition from Disconnected to Connecting state via CONNECT message */ @@ -219,9 +215,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); } /** @@ -246,9 +241,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); } /** @@ -273,9 +267,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); } /** @@ -296,9 +289,8 @@ public class HeadsetStateMachineTest { verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)) .sendBroadcastAsUser( any(Intent.class), any(UserHandle.class), anyString(), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); // Indicate connection failed to test state machine mHeadsetStateMachine.sendMessage( @@ -320,9 +312,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** Test state transition from Connecting to Disconnected state via CONNECT_TIMEOUT message */ @@ -342,9 +333,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** @@ -364,9 +354,8 @@ public class HeadsetStateMachineTest { verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)) .sendBroadcastAsUser( any(Intent.class), any(UserHandle.class), anyString(), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); // Indicate RFCOMM connection is successful to test state machine mHeadsetStateMachine.sendMessage( @@ -379,9 +368,8 @@ public class HeadsetStateMachineTest { verify(mHeadsetService, after(ASYNC_CALL_TIMEOUT_MILLIS).times(numBroadcastsSent)) .sendBroadcastAsUser( any(Intent.class), any(UserHandle.class), anyString(), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); // Indicate SLC connection is successful to test state machine numBroadcastsSent++; @@ -402,9 +390,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** @@ -433,9 +420,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** @@ -457,9 +443,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** @@ -488,9 +473,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** Test state transition from Connected to Disconnecting state via DISCONNECT message */ @@ -511,9 +495,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); } /** @@ -542,9 +525,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); } /** @@ -573,9 +555,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** Test state transition from Connected to AudioConnecting state via CONNECT_AUDIO message */ @@ -596,9 +577,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioConnecting.class); } /** @@ -616,9 +596,8 @@ public class HeadsetStateMachineTest { // verify no native connect audio verify(mNativeInterface, never()).connectAudio(mTestDevice); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioConnecting.class); Utils.setIsScoManagedByAudioEnabled(false); } @@ -648,9 +627,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioConnecting.class); } /** @@ -678,9 +656,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioOn.class); } /** Test state transition from AudioConnecting to Connected state via CONNECT_TIMEOUT message */ @@ -700,9 +677,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** @@ -731,9 +707,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** @@ -767,9 +742,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** @@ -803,9 +777,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); } /** @@ -834,9 +807,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioOn.class); } /** @@ -859,9 +831,8 @@ public class HeadsetStateMachineTest { eq(UserHandle.ALL), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioDisconnecting.class); } /** @@ -879,9 +850,8 @@ public class HeadsetStateMachineTest { eq(UserHandle.ALL), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioDisconnecting.class); } /** @@ -910,9 +880,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** Test state transition from AudioOn to Disconnected state via Stack.DISCONNECTED message */ @@ -943,9 +912,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** Test state transition from AudioOn to Disconnecting state via Stack.DISCONNECTING message */ @@ -976,9 +944,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); } /** @@ -1000,9 +967,8 @@ public class HeadsetStateMachineTest { eq(UserHandle.ALL), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioDisconnecting.class); if (i == MAX_RETRY_DISCONNECT_AUDIO) { // Increment twice numBroadcastsSent as DISCONNECT message is added on max retry numBroadcastsSent += 2; @@ -1024,18 +990,16 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioOn.class); } else { // Max retry count reached, test Disconnecting state HeadsetTestUtils.verifyConnectionStateBroadcast( mTestDevice, BluetoothHeadset.STATE_DISCONNECTING, BluetoothHeadset.STATE_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); } } } @@ -1066,9 +1030,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_DISCONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); } /** @@ -1097,9 +1060,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioOn.class); } /** @@ -1133,9 +1095,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); } /** @@ -1169,9 +1130,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getAllValues().get(mIntentArgument.getAllValues().size() - 1)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnected.class); } /** @@ -1331,7 +1291,7 @@ public class HeadsetStateMachineTest { verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)).disconnectAudio(mTestDevice); } - /** A test to verfiy that we correctly handles AT+BIND event with driver safety case from HF */ + /** A test to verify that we correctly handles AT+BIND event with driver safety case from HF */ @Test public void testAtBindWithDriverSafetyEventWhenConnecting() { setUpConnectingState(); @@ -1344,22 +1304,21 @@ public class HeadsetStateMachineTest { verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) .sendBroadcast(intentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); verify(mHeadsetService).sendBroadcast(any(), any(), any()); - Assert.assertEquals( - mTestDevice, - intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)); - Assert.assertEquals( - HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)); - Assert.assertEquals( - -1, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)); + assertThat(intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)) + .isEqualTo(mTestDevice); + assertThat( + intentArgument + .getValue() + .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)) + .isEqualTo(HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY); + assertThat( + intentArgument + .getValue() + .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)) + .isEqualTo(-1); } - /** A test to verfiy that we correctly handles AT+BIND event with battery level case from HF */ + /** A test to verify that we correctly handles AT+BIND event with battery level case from HF */ @Test public void testAtBindEventWithBatteryLevelEventWhenConnecting() { setUpConnectingState(); @@ -1372,22 +1331,21 @@ public class HeadsetStateMachineTest { verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) .sendBroadcast(intentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); verify(mHeadsetService).sendBroadcast(any(), any(), any()); - Assert.assertEquals( - mTestDevice, - intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)); - Assert.assertEquals( - HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)); - Assert.assertEquals( - -1, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)); + assertThat(intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)) + .isEqualTo(mTestDevice); + assertThat( + intentArgument + .getValue() + .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)) + .isEqualTo(HeadsetHalConstants.HF_INDICATOR_BATTERY_LEVEL_STATUS); + assertThat( + intentArgument + .getValue() + .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)) + .isEqualTo(-1); } - /** A test to verfiy that we correctly handles AT+BIND event with error case from HF */ + /** A test to verify that we correctly handles AT+BIND event with error case from HF */ @Test public void testAtBindEventWithErrorEventWhenConnecting() { setUpConnectingState(); @@ -1400,19 +1358,18 @@ public class HeadsetStateMachineTest { verify(mHeadsetService, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) .sendBroadcast(intentArgument.capture(), eq(BLUETOOTH_CONNECT), any(Bundle.class)); verify(mHeadsetService).sendBroadcast(any(), any(), any()); - Assert.assertEquals( - mTestDevice, - intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)); - Assert.assertEquals( - HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)); - Assert.assertEquals( - -1, - intentArgument - .getValue() - .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)); + assertThat(intentArgument.getValue().getExtra(BluetoothDevice.EXTRA_DEVICE, null)) + .isEqualTo(mTestDevice); + assertThat( + intentArgument + .getValue() + .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_ID, -1)) + .isEqualTo(HeadsetHalConstants.HF_INDICATOR_ENHANCED_DRIVER_SAFETY); + assertThat( + intentArgument + .getValue() + .getIntExtra(BluetoothHeadset.EXTRA_HF_INDICATORS_IND_VALUE, -2)) + .isEqualTo(-1); } /** A test to verify that we correctly set AG indicator mask when enter/exit silence mode */ @@ -1442,7 +1399,7 @@ public class HeadsetStateMachineTest { String input = "test"; int fromIndex = 0; - Assert.assertEquals(HeadsetStateMachine.findChar(ch, input, fromIndex), 2); + assertThat(HeadsetStateMachine.findChar(ch, input, fromIndex)).isEqualTo(2); } @Test @@ -1451,7 +1408,7 @@ public class HeadsetStateMachineTest { String input = "test"; int fromIndex = 0; - Assert.assertEquals(HeadsetStateMachine.findChar(ch, input, fromIndex), input.length()); + assertThat(HeadsetStateMachine.findChar(ch, input, fromIndex)).isEqualTo(input.length()); } @Test @@ -1460,7 +1417,7 @@ public class HeadsetStateMachineTest { String input = "te\"st"; int fromIndex = 0; - Assert.assertEquals(HeadsetStateMachine.findChar(ch, input, fromIndex), input.length()); + assertThat(HeadsetStateMachine.findChar(ch, input, fromIndex)).isEqualTo(input.length()); } @Test @@ -1470,46 +1427,47 @@ public class HeadsetStateMachineTest { expected.add(11); expected.add("notint"); - Assert.assertEquals(HeadsetStateMachine.generateArgs(input), expected.toArray()); + assertThat(HeadsetStateMachine.generateArgs(input)).isEqualTo(expected.toArray()); } @Test public void testGetAtCommandType() { String atCommand = "start?"; - Assert.assertEquals( - mHeadsetStateMachine.getAtCommandType(atCommand), AtPhonebook.TYPE_READ); + assertThat(mHeadsetStateMachine.getAtCommandType(atCommand)) + .isEqualTo(AtPhonebook.TYPE_READ); atCommand = "start=?"; - Assert.assertEquals( - mHeadsetStateMachine.getAtCommandType(atCommand), AtPhonebook.TYPE_TEST); + assertThat(mHeadsetStateMachine.getAtCommandType(atCommand)) + .isEqualTo(AtPhonebook.TYPE_TEST); atCommand = "start=comm"; - Assert.assertEquals(mHeadsetStateMachine.getAtCommandType(atCommand), AtPhonebook.TYPE_SET); + assertThat(mHeadsetStateMachine.getAtCommandType(atCommand)) + .isEqualTo(AtPhonebook.TYPE_SET); atCommand = "start!"; - Assert.assertEquals( - mHeadsetStateMachine.getAtCommandType(atCommand), AtPhonebook.TYPE_UNKNOWN); + assertThat(mHeadsetStateMachine.getAtCommandType(atCommand)) + .isEqualTo(AtPhonebook.TYPE_UNKNOWN); } @Test public void testParseUnknownAt() { String atString = "\"command\""; - Assert.assertEquals(mHeadsetStateMachine.parseUnknownAt(atString), "\"command\""); + assertThat(mHeadsetStateMachine.parseUnknownAt(atString)).isEqualTo("\"command\""); } @Test public void testParseUnknownAt_withUnmatchingQuotes() { String atString = "\"command"; - Assert.assertEquals(mHeadsetStateMachine.parseUnknownAt(atString), "\"command\""); + assertThat(mHeadsetStateMachine.parseUnknownAt(atString)).isEqualTo("\"command\""); } @Test public void testParseUnknownAt_withCharOutsideQuotes() { String atString = "a\"command\""; - Assert.assertEquals(mHeadsetStateMachine.parseUnknownAt(atString), "A\"command\""); + assertThat(mHeadsetStateMachine.parseUnknownAt(atString)).isEqualTo("A\"command\""); } @Ignore("b/265556073") @@ -1803,7 +1761,7 @@ public class HeadsetStateMachineTest { mHeadsetStateMachine.processVolumeEvent(HeadsetHalConstants.VOLUME_TYPE_MIC, 1); - Assert.assertEquals(mHeadsetStateMachine.mMicVolume, 1); + assertThat(mHeadsetStateMachine.mMicVolume).isEqualTo(1); } @RequiresFlagsDisabled(FLAG_DEPRECATE_STREAM_BT_SCO) @@ -1816,7 +1774,7 @@ public class HeadsetStateMachineTest { mHeadsetStateMachine.processVolumeEvent(HeadsetHalConstants.VOLUME_TYPE_SPK, 2); - Assert.assertEquals(mHeadsetStateMachine.mSpeakerVolume, 2); + assertThat(mHeadsetStateMachine.mSpeakerVolume).isEqualTo(2); verify(mockAudioManager).setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, 2, 0); } @@ -1830,7 +1788,7 @@ public class HeadsetStateMachineTest { mHeadsetStateMachine.processVolumeEvent(HeadsetHalConstants.VOLUME_TYPE_SPK, 2); - Assert.assertEquals(mHeadsetStateMachine.mSpeakerVolume, 2); + assertThat(mHeadsetStateMachine.mSpeakerVolume).isEqualTo(2); verify(mockAudioManager).setStreamVolume(AudioManager.STREAM_VOICE_CALL, 2, 0); } @@ -2169,9 +2127,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); return 1; } @@ -2199,9 +2156,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connecting.class); mHeadsetStateMachine.sendMessage( HeadsetStateMachine.STACK_EVENT, new HeadsetStackEvent( @@ -2219,9 +2175,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Connected.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Connected.class); return 2; } @@ -2241,9 +2196,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTING, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioConnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioConnecting.class); return numBroadcastsSent; } @@ -2268,9 +2222,8 @@ public class HeadsetStateMachineTest { BluetoothHeadset.STATE_AUDIO_CONNECTED, BluetoothHeadset.STATE_AUDIO_CONNECTING, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioOn.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioOn.class); return numBroadcastsSent; } @@ -2284,9 +2237,8 @@ public class HeadsetStateMachineTest { eq(UserHandle.ALL), eq(BLUETOOTH_CONNECT), any(Bundle.class)); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.AudioDisconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.AudioDisconnecting.class); return numBroadcastsSent; } @@ -2306,9 +2258,8 @@ public class HeadsetStateMachineTest { BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED, mIntentArgument.getValue()); - Assert.assertThat( - mHeadsetStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(HeadsetStateMachine.Disconnecting.class)); + assertThat(mHeadsetStateMachine.getCurrentState()) + .isInstanceOf(HeadsetStateMachine.Disconnecting.class); return numBroadcastsSent; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java index e80048dafa..4b2d0b291c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java @@ -25,8 +25,6 @@ import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; import android.content.Intent; -import org.junit.Assert; - /** Helper functions for HFP related tests */ public class HeadsetTestUtils { @@ -41,11 +39,12 @@ public class HeadsetTestUtils { public static void verifyAudioStateBroadcast( BluetoothDevice device, int toState, int fromState, Intent intent) { assertThat(intent).isNotNull(); - Assert.assertEquals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED, intent.getAction()); - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(toState, intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertEquals( - fromState, intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)); + assertThat(intent.getAction()).isEqualTo(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(device); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)).isEqualTo(toState); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)) + .isEqualTo(fromState); } /** @@ -61,14 +60,15 @@ public class HeadsetTestUtils { public static void verifyConnectionStateBroadcast( BluetoothDevice device, int toState, int fromState, Intent intent, boolean checkFlag) { assertThat(intent).isNotNull(); - Assert.assertEquals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED, intent.getAction()); + assertThat(intent.getAction()).isEqualTo(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); if (checkFlag) { - Assert.assertEquals(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, intent.getFlags()); + assertThat(intent.getFlags()).isEqualTo(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); } - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(toState, intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertEquals( - fromState, intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(device); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)).isEqualTo(toState); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)) + .isEqualTo(fromState); } /** @@ -97,13 +97,14 @@ public class HeadsetTestUtils { public static void verifyActiveDeviceChangedBroadcast( BluetoothDevice device, Intent intent, boolean checkFlag) { assertThat(intent).isNotNull(); - Assert.assertEquals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, intent.getAction()); - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); + assertThat(intent.getAction()).isEqualTo(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(device); if (checkFlag) { - Assert.assertEquals( - Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, - intent.getFlags()); + assertThat(intent.getFlags()) + .isEqualTo( + Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java index 3541670116..543aca2578 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java @@ -39,8 +39,6 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.media.AudioManager; import android.os.BatteryManager; -import android.platform.test.annotations.EnableFlags; -import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; @@ -49,10 +47,8 @@ import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.RemoteDevices; import com.android.bluetooth.btservice.storage.DatabaseManager; -import com.android.bluetooth.flags.Flags; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -71,7 +67,6 @@ import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) public class HeadsetClientServiceTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private AdapterService mAdapterService; @Mock private HeadsetClientStateMachine mStateMachine; @@ -211,7 +206,6 @@ public class HeadsetClientServiceTest { * back HF values and checks if they match AM. This proves that the conversion is symmetric. */ @Test - @EnableFlags(Flags.FLAG_HEADSET_CLIENT_AM_HF_VOLUME_SYMMETRIC) public void testAmHfVolumeSymmetric_AmLowerRange() { int amMin = 1; int amMax = 10; @@ -231,7 +225,7 @@ public class HeadsetClientServiceTest { for (Map.Entry entry : amToHfMap.entrySet()) { // Convert back from collected HF to AM and check if equal the saved AM value - Assert.assertEquals(service.hfToAmVol((int) entry.getValue()), entry.getKey()); + assertThat(service.hfToAmVol((int) entry.getValue())).isEqualTo(entry.getKey()); } } @@ -241,7 +235,6 @@ public class HeadsetClientServiceTest { * back AM values and checks if they match HF. This proves that the conversion is symmetric. */ @Test - @EnableFlags(Flags.FLAG_HEADSET_CLIENT_AM_HF_VOLUME_SYMMETRIC) public void testAmHfVolumeSymmetric_HfLowerRange() { int amMin = 1; int amMax = 20; @@ -261,7 +254,7 @@ public class HeadsetClientServiceTest { for (Map.Entry entry : hfToAmMap.entrySet()) { // Convert back from collected AM to HF and check if equal the saved HF value - Assert.assertEquals(service.amToHfVol((int) entry.getValue()), entry.getKey()); + assertThat(service.amToHfVol((int) entry.getValue())).isEqualTo(entry.getKey()); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java index fc33b519d7..337fb1faa3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java @@ -41,7 +41,6 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -124,7 +123,7 @@ public class HidDeviceTest { field.setAccessible(true); HidDeviceNativeInterface nativeInterface = (HidDeviceNativeInterface) field.get(mHidDeviceService); - Assert.assertEquals(nativeInterface, mHidDeviceNativeInterface); + assertThat(nativeInterface).isEqualTo(mHidDeviceNativeInterface); // Dummy SDP settings mSettings = @@ -184,11 +183,13 @@ public class HidDeviceTest { int timeoutMs, BluetoothDevice device, int newState, int prevState) { Intent intent = waitForIntent(timeoutMs, mConnectionStateChangedQueue); assertThat(intent).isNotNull(); - Assert.assertEquals(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED, intent.getAction()); - Assert.assertEquals(device, intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); - Assert.assertEquals(newState, intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)); - Assert.assertEquals( - prevState, intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)); + assertThat(intent.getAction()) + .isEqualTo(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(device); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)).isEqualTo(newState); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)) + .isEqualTo(prevState); } private void verifyCallback(int timeoutMs, int callbackType, BlockingQueue<Integer> queue) { @@ -196,7 +197,7 @@ public class HidDeviceTest { Integer lastCallback = queue.poll(timeoutMs, TimeUnit.MILLISECONDS); assertThat(lastCallback).isNotNull(); int lastCallbackType = lastCallback; - Assert.assertEquals(callbackType, lastCallbackType); + assertThat(callbackType).isEqualTo(lastCallbackType); } catch (InterruptedException e) { throw new AssertionError("Cannot obtain a callback from the queue", e); } @@ -261,7 +262,7 @@ public class HidDeviceTest { /** Test getting HidDeviceService: getHidDeviceService(). */ @Test public void testGetHidDeviceService() { - Assert.assertEquals(mHidDeviceService, HidDeviceService.getHidDeviceService()); + assertThat(HidDeviceService.getHidDeviceService()).isEqualTo(mHidDeviceService); } /** @@ -311,7 +312,7 @@ public class HidDeviceTest { // Unregister app doReturn(true).when(mHidDeviceNativeInterface).unregisterApp(); - Assert.assertEquals(true, mHidDeviceService.unregisterApp()); + assertThat(mHidDeviceService.unregisterApp()).isTrue(); verify(mHidDeviceNativeInterface).unregisterApp(); @@ -324,9 +325,8 @@ public class HidDeviceTest { public void testSendReport() throws Exception { doReturn(true).when(mHidDeviceNativeInterface).sendReport(anyInt(), any(byte[].class)); // sendReport() should fail without app registered - Assert.assertEquals( - false, - mHidDeviceService.sendReport(mTestDevice, SAMPLE_REPORT_ID, SAMPLE_HID_REPORT)); + assertThat(mHidDeviceService.sendReport(mTestDevice, SAMPLE_REPORT_ID, SAMPLE_HID_REPORT)) + .isFalse(); // Register app doReturn(true) @@ -349,16 +349,15 @@ public class HidDeviceTest { verifyCallback(TIMEOUT_MS, CALLBACK_APP_REGISTERED, mCallbackQueue); // sendReport() should work when app is registered - Assert.assertEquals( - true, - mHidDeviceService.sendReport(mTestDevice, SAMPLE_REPORT_ID, SAMPLE_HID_REPORT)); + assertThat(mHidDeviceService.sendReport(mTestDevice, SAMPLE_REPORT_ID, SAMPLE_HID_REPORT)) + .isTrue(); verify(mHidDeviceNativeInterface) .sendReport(eq((int) SAMPLE_REPORT_ID), eq(SAMPLE_HID_REPORT)); // Unregister app doReturn(true).when(mHidDeviceNativeInterface).unregisterApp(); - Assert.assertEquals(true, mHidDeviceService.unregisterApp()); + assertThat(mHidDeviceService.unregisterApp()).isTrue(); } /** Test the logic in replyReport(). This should fail when the app is not registered. */ @@ -368,10 +367,13 @@ public class HidDeviceTest { .when(mHidDeviceNativeInterface) .replyReport(anyByte(), anyByte(), any(byte[].class)); // replyReport() should fail without app registered - Assert.assertEquals( - false, - mHidDeviceService.replyReport( - mTestDevice, SAMPLE_REPORT_TYPE, SAMPLE_REPORT_ID, SAMPLE_HID_REPORT)); + assertThat( + mHidDeviceService.replyReport( + mTestDevice, + SAMPLE_REPORT_TYPE, + SAMPLE_REPORT_ID, + SAMPLE_HID_REPORT)) + .isFalse(); // Register app doReturn(true) @@ -394,17 +396,20 @@ public class HidDeviceTest { verifyCallback(TIMEOUT_MS, CALLBACK_APP_REGISTERED, mCallbackQueue); // replyReport() should work when app is registered - Assert.assertEquals( - true, - mHidDeviceService.replyReport( - mTestDevice, SAMPLE_REPORT_TYPE, SAMPLE_REPORT_ID, SAMPLE_HID_REPORT)); + assertThat( + mHidDeviceService.replyReport( + mTestDevice, + SAMPLE_REPORT_TYPE, + SAMPLE_REPORT_ID, + SAMPLE_HID_REPORT)) + .isTrue(); verify(mHidDeviceNativeInterface) .replyReport(eq(SAMPLE_REPORT_TYPE), eq(SAMPLE_REPORT_ID), eq(SAMPLE_HID_REPORT)); // Unregister app doReturn(true).when(mHidDeviceNativeInterface).unregisterApp(); - Assert.assertEquals(true, mHidDeviceService.unregisterApp()); + assertThat(mHidDeviceService.unregisterApp()).isTrue(); } /** Test the logic in reportError(). This should fail when the app is not registered. */ @@ -412,7 +417,7 @@ public class HidDeviceTest { public void testReportError() throws Exception { doReturn(true).when(mHidDeviceNativeInterface).reportError(anyByte()); // reportError() should fail without app registered - Assert.assertEquals(false, mHidDeviceService.reportError(mTestDevice, SAMPLE_REPORT_ERROR)); + assertThat(mHidDeviceService.reportError(mTestDevice, SAMPLE_REPORT_ERROR)).isFalse(); // Register app doReturn(true) @@ -435,13 +440,13 @@ public class HidDeviceTest { verifyCallback(TIMEOUT_MS, CALLBACK_APP_REGISTERED, mCallbackQueue); // reportError() should work when app is registered - Assert.assertEquals(true, mHidDeviceService.reportError(mTestDevice, SAMPLE_REPORT_ERROR)); + assertThat(mHidDeviceService.reportError(mTestDevice, SAMPLE_REPORT_ERROR)).isTrue(); verify(mHidDeviceNativeInterface).reportError(eq(SAMPLE_REPORT_ERROR)); // Unregister app doReturn(true).when(mHidDeviceNativeInterface).unregisterApp(); - Assert.assertEquals(true, mHidDeviceService.unregisterApp()); + assertThat(mHidDeviceService.unregisterApp()).isTrue(); } /** Test that an outgoing connection/disconnection succeeds */ @@ -477,9 +482,8 @@ public class HidDeviceTest { mTestDevice, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, - mHidDeviceService.getConnectionState(mTestDevice)); + assertThat(mHidDeviceService.getConnectionState(mTestDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); mHidDeviceService.onConnectStateChangedFromNative( mTestDevice, HidDeviceService.HAL_CONN_STATE_CONNECTED); @@ -489,9 +493,8 @@ public class HidDeviceTest { mTestDevice, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, - mHidDeviceService.getConnectionState(mTestDevice)); + assertThat(mHidDeviceService.getConnectionState(mTestDevice)) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); // Verify the list of connected devices assertThat( @@ -510,9 +513,8 @@ public class HidDeviceTest { mTestDevice, BluetoothProfile.STATE_DISCONNECTING, BluetoothProfile.STATE_CONNECTED); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTING, - mHidDeviceService.getConnectionState(mTestDevice)); + assertThat(mHidDeviceService.getConnectionState(mTestDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTING); mHidDeviceService.onConnectStateChangedFromNative( mTestDevice, HidDeviceService.HAL_CONN_STATE_DISCONNECTED); @@ -522,9 +524,8 @@ public class HidDeviceTest { mTestDevice, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_DISCONNECTING); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, - mHidDeviceService.getConnectionState(mTestDevice)); + assertThat(mHidDeviceService.getConnectionState(mTestDevice)) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); // Verify the list of connected devices assertThat( @@ -534,7 +535,7 @@ public class HidDeviceTest { // Unregister app doReturn(true).when(mHidDeviceNativeInterface).unregisterApp(); - Assert.assertEquals(true, mHidDeviceService.unregisterApp()); + assertThat(mHidDeviceService.unregisterApp()).isTrue(); } /** @@ -607,7 +608,7 @@ public class HidDeviceTest { // Unregister app doReturn(true).when(mHidDeviceNativeInterface).unregisterApp(); - Assert.assertEquals(true, mHidDeviceService.unregisterApp()); + assertThat(mHidDeviceService.unregisterApp()).isTrue(); verify(mHidDeviceNativeInterface).unregisterApp(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java index 39de9c8e0f..bf519011bb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java @@ -110,7 +110,6 @@ public class HidHostServiceBinderTest { @Test public void setPreferredTransport_callsServiceMethod() { - mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP); int preferredTransport = BluetoothDevice.TRANSPORT_AUTO; mBinder.setPreferredTransport(mRemoteDevice, preferredTransport, null); @@ -119,7 +118,6 @@ public class HidHostServiceBinderTest { @Test public void getPreferredTransport_callsServiceMethod() { - mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP); mBinder.getPreferredTransport(mRemoteDevice, null); verify(mService).getPreferredTransport(mRemoteDevice); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java index 7cf714c142..878279dae0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java @@ -33,7 +33,6 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -176,10 +175,10 @@ public class HidHostServiceTest { // Test when the AdapterService is in non-quiet mode. doReturn(false).when(mAdapterService).isQuietModeEnabled(); - Assert.assertEquals(expected, mService.okToConnect(device)); + assertThat(mService.okToConnect(device)).isEqualTo(expected); // Test when the AdapterService is in quiet mode. doReturn(true).when(mAdapterService).isQuietModeEnabled(); - Assert.assertEquals(false, mService.okToConnect(device)); + assertThat(mService.okToConnect(device)).isFalse(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java index fdd2aacad0..3750a72055 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java @@ -69,10 +69,10 @@ public class ContentControlIdKeeperTest { verify(mLeAudioServiceMock).setCcidInformation(eq(uuid), eq(ccid), eq(context)); Map<ParcelUuid, Pair<Integer, Integer>> uuidToCcidContextPair = ContentControlIdKeeper.getUuidToCcidContextPairMap(); - Assert.assertEquals(expectedListSize, uuidToCcidContextPair.size()); + assertThat(uuidToCcidContextPair.size()).isEqualTo(expectedListSize); assertThat(uuidToCcidContextPair).containsKey(uuid); - Assert.assertEquals(ccid, (long) uuidToCcidContextPair.get(uuid).first); - Assert.assertEquals(context, (long) uuidToCcidContextPair.get(uuid).second); + assertThat(uuidToCcidContextPair.get(uuid).first).isEqualTo(ccid); + assertThat(uuidToCcidContextPair.get(uuid).second).isEqualTo(context); return ccid; } @@ -88,7 +88,7 @@ public class ContentControlIdKeeperTest { verify(mLeAudioServiceMock).setCcidInformation(eq(uuid), eq(ccid), eq(0)); - Assert.assertEquals(expectedListSize, uuidToCcidContextPair.size()); + assertThat(uuidToCcidContextPair.size()).isEqualTo(expectedListSize); } @Test @@ -120,14 +120,14 @@ public class ContentControlIdKeeperTest { public void testAcquireInvalidContext() { ParcelUuid uuid = new ParcelUuid(UUID.randomUUID()); - int ccid = ContentControlIdKeeper.acquireCcid(uuid, 0); - Assert.assertEquals(ccid, ContentControlIdKeeper.CCID_INVALID); + assertThat(ContentControlIdKeeper.acquireCcid(uuid, 0)) + .isEqualTo(ContentControlIdKeeper.CCID_INVALID); verify(mLeAudioServiceMock, times(0)) .setCcidInformation(any(ParcelUuid.class), any(int.class), any(int.class)); Map<ParcelUuid, Pair<Integer, Integer>> uuidToCcidContextPair = ContentControlIdKeeper.getUuidToCcidContextPairMap(); - Assert.assertEquals(0, uuidToCcidContextPair.size()); + assertThat(uuidToCcidContextPair).isEmpty(); } @Test @@ -138,6 +138,6 @@ public class ContentControlIdKeeperTest { int ccid_two = testCcidAcquire(uuid, BluetoothLeAudio.CONTEXT_TYPE_RINGTONE, 1); // This is implementation specific but verifies that the previous CCID was recycled - Assert.assertEquals(ccid_one, ccid_two); + assertThat(ccid_two).isEqualTo(ccid_one); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 5fbee5c0b7..340ebf85eb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -237,7 +237,7 @@ public class LeAudioBroadcastServiceTest { /** Test getting LeAudio Service */ @Test public void testGetLeAudioService() { - Assert.assertEquals(mService, LeAudioService.getLeAudioService()); + assertThat(LeAudioService.getLeAudioService()).isEqualTo(mService); } void verifyBroadcastStarted(int broadcastId, BluetoothLeBroadcastSettings settings) { @@ -753,7 +753,7 @@ public class LeAudioBroadcastServiceTest { List<BluetoothLeBroadcastMetadata> meta_list = mService.getAllBroadcastMetadata(); assertThat(meta_list).isNotNull(); Assert.assertNotEquals(meta_list.size(), 0); - Assert.assertEquals(meta_list.get(0), state_event.broadcastMetadata); + assertThat(meta_list.get(0)).isEqualTo(state_event.broadcastMetadata); } @Test @@ -806,13 +806,13 @@ public class LeAudioBroadcastServiceTest { int timeoutMs, BluetoothDevice device, int newState, int prevState) { Intent intent = TestUtils.waitForIntent(timeoutMs, mIntentQueue); assertThat(intent).isNotNull(); - Assert.assertEquals( - BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED, intent.getAction()); - Assert.assertEquals( - (BluetoothDevice) intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE), device); - Assert.assertEquals(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1), newState); - Assert.assertEquals( - intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1), prevState); + assertThat(intent.getAction()) + .isEqualTo(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED); + assertThat(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class)) + .isEqualTo(device); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1)).isEqualTo(newState); + assertThat(intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1)) + .isEqualTo(prevState); if (newState == BluetoothProfile.STATE_CONNECTED) { // ActiveDeviceManager calls deviceConnected when connected. @@ -854,7 +854,8 @@ public class LeAudioBroadcastServiceTest { device, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_DISCONNECTED); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device)); + assertThat(mService.getConnectionState(device)) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); LeAudioStackEvent create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -867,7 +868,7 @@ public class LeAudioBroadcastServiceTest { device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_CONNECTING); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device)); + assertThat(mService.getConnectionState(device)).isEqualTo(BluetoothProfile.STATE_CONNECTED); create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_NODE_STATUS_CHANGED); @@ -889,6 +890,8 @@ public class LeAudioBroadcastServiceTest { injectGroupSelectableCodecConfigChanged( groupId, INPUT_SELECTABLE_CONFIG_HIGH, OUTPUT_SELECTABLE_CONFIG_HIGH); injectGroupCurrentCodecConfigChanged(groupId, LC3_16KHZ_CONFIG, LC3_48KHZ_CONFIG); + + mService.deviceConnected(device); } @Test @@ -932,7 +935,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become inactive */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, LE_AUDIO_GROUP_ID_INVALID); + assertThat(activeGroup).isEqualTo(LE_AUDIO_GROUP_ID_INVALID); /* Imitate group inactivity to cause create broadcast */ stackEvent = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); @@ -959,7 +962,7 @@ public class LeAudioBroadcastServiceTest { eq(expectedDataArray)); activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(-1, activeGroup); + assertThat(activeGroup).isEqualTo(-1); } @Test @@ -1046,7 +1049,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become inactive */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, LE_AUDIO_GROUP_ID_INVALID); + assertThat(activeGroup).isEqualTo(LE_AUDIO_GROUP_ID_INVALID); /* Imitate group inactivity to cause create broadcast */ create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); @@ -1088,7 +1091,7 @@ public class LeAudioBroadcastServiceTest { } activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(LE_AUDIO_GROUP_ID_INVALID, activeGroup); + assertThat(activeGroup).isEqualTo(LE_AUDIO_GROUP_ID_INVALID); /* Check if broadcast is started automatically when created */ create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED); @@ -1107,12 +1110,17 @@ public class LeAudioBroadcastServiceTest { } @Test + @DisableFlags(Flags.FLAG_LEAUDIO_USE_AUDIO_RECORDING_LISTENER) public void testInCallDrivenBroadcastSwitch() { mSetFlagsRule.disableFlags(Flags.FLAG_LEAUDIO_USE_AUDIO_MODE_LISTENER); int groupId = 1; int broadcastId = 243; byte[] code = {0x00, 0x01, 0x00, 0x02}; + List<BluetoothDevice> devices = new ArrayList<>(); + when(mDatabaseManager.getMostRecentlyConnectedDevices()).thenReturn(devices); + + devices.add(mDevice); prepareHandoverStreamingBroadcast(groupId, broadcastId, code); /* Imitate setting device in call */ @@ -1153,7 +1161,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become the one that was active before broadcasting */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, groupId); + assertThat(activeGroup).isEqualTo(groupId); /* Imitate setting device not in call */ mService.setInCall(false); @@ -1230,7 +1238,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become the one that was active before broadcasting */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, groupId); + assertThat(activeGroup).isEqualTo(groupId); /* Imitate group change request by Bluetooth Sink HAL suspend request */ create_event = @@ -1325,7 +1333,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become the one that was active before broadcasting */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, groupId); + assertThat(activeGroup).isEqualTo(groupId); /* Imitate group change request by Bluetooth Sink HAL suspend request */ create_event = @@ -1365,13 +1373,18 @@ public class LeAudioBroadcastServiceTest { } @Test + @DisableFlags(Flags.FLAG_LEAUDIO_USE_AUDIO_RECORDING_LISTENER) public void testInCallDrivenBroadcastSwitchDuringInternalPause() { mSetFlagsRule.disableFlags(Flags.FLAG_LEAUDIO_USE_AUDIO_MODE_LISTENER); mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE); int groupId = 1; int broadcastId = 243; byte[] code = {0x00, 0x01, 0x00, 0x02}; + List<BluetoothDevice> devices = new ArrayList<>(); + + when(mDatabaseManager.getMostRecentlyConnectedDevices()).thenReturn(devices); + devices.add(mDevice); prepareHandoverStreamingBroadcast(groupId, broadcastId, code); /* Internal broadcast paused due to onAudioSuspend */ @@ -1413,7 +1426,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become the one that was active before broadcasting */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, groupId); + assertThat(activeGroup).isEqualTo(groupId); /* Imitate setting device not in call */ mService.setInCall(false); @@ -1491,7 +1504,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become the one that was active before broadcasting */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, groupId); + assertThat(activeGroup).isEqualTo(groupId); /* Imitate group change request by Bluetooth Sink HAL suspend request */ create_event = @@ -1581,7 +1594,7 @@ public class LeAudioBroadcastServiceTest { /* Active group should become the one that was active before broadcasting */ int activeGroup = mService.getActiveGroupId(); - Assert.assertEquals(activeGroup, groupId); + assertThat(activeGroup).isEqualTo(groupId); /* Imitate group change request by Bluetooth Sink HAL suspend request */ create_event = @@ -1657,7 +1670,7 @@ public class LeAudioBroadcastServiceTest { prepareConnectedUnicastDevice(groupId2, mDevice2); prepareHandoverStreamingBroadcast(groupId, broadcastId, code); - Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId); + assertThat(mService.mUnicastGroupIdDeactivatedForBroadcastTransition).isEqualTo(groupId); reset(mAudioManager); @@ -1674,19 +1687,25 @@ public class LeAudioBroadcastServiceTest { eq(mDevice2), eq(mDevice), connectionInfoArgumentCaptor.capture()); List<BluetoothProfileConnectionInfo> connInfos = connectionInfoArgumentCaptor.getAllValues(); - Assert.assertEquals(connInfos.size(), 1); + assertThat(connInfos.size()).isEqualTo(1); assertThat(connInfos.get(0).isLeOutput()).isFalse(); } - Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId2); + assertThat(mService.mUnicastGroupIdDeactivatedForBroadcastTransition).isEqualTo(groupId2); } @Test - @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP) + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP, + Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION + }) public void testOnBroadcastToUnicastFallbackGroupChanged() { int groupId1 = 1; int groupId2 = 2; int broadcastId = 243; byte[] code = {0x00, 0x01, 0x00, 0x02}; + List<BluetoothDevice> devices = new ArrayList<>(); + + when(mDatabaseManager.getMostRecentlyConnectedDevices()).thenReturn(devices); onBroadcastToUnicastFallbackGroupChangedCallbackCalled = false; @@ -1710,7 +1729,7 @@ public class LeAudioBroadcastServiceTest { @Override public void onBroadcastToUnicastFallbackGroupChanged(int groupId) { onBroadcastToUnicastFallbackGroupChangedCallbackCalled = true; - Assert.assertEquals(groupId1, groupId); + assertThat(groupId2).isEqualTo(groupId); } }; @@ -1719,11 +1738,13 @@ public class LeAudioBroadcastServiceTest { } initializeNative(); + devices.add(mDevice2); prepareConnectedUnicastDevice(groupId2, mDevice2); + devices.add(mDevice); prepareHandoverStreamingBroadcast(groupId1, broadcastId, code); TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); - Assert.assertEquals(groupId1, mService.mUnicastGroupIdDeactivatedForBroadcastTransition); + assertThat(mService.mUnicastGroupIdDeactivatedForBroadcastTransition).isEqualTo(groupId2); assertThat(onBroadcastToUnicastFallbackGroupChangedCallbackCalled).isTrue(); onBroadcastToUnicastFallbackGroupChangedCallbackCalled = false; @@ -1764,9 +1785,8 @@ public class LeAudioBroadcastServiceTest { mService.deviceConnected(mDevice); devices.add(mDevice2); prepareConnectedUnicastDevice(groupId2, mDevice2); - mService.deviceConnected(mDevice2); - Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId); + assertThat(mService.mUnicastGroupIdDeactivatedForBroadcastTransition).isEqualTo(groupId); reset(mAudioManager); @@ -1789,6 +1809,88 @@ public class LeAudioBroadcastServiceTest { Assert.assertEquals(mService.getBroadcastToUnicastFallbackGroup(), groupId2); } + private void disconnectDevice(BluetoothDevice device) { + doReturn(true).when(mLeAudioNativeInterface).disconnectLeAudio(any(BluetoothDevice.class)); + assertThat(mService.disconnect(device)).isTrue(); + + // Verify the connection state broadcast, and that we are in Connected state + verifyConnectionStateIntent( + TIMEOUT_MS, + device, + BluetoothProfile.STATE_DISCONNECTING, + BluetoothProfile.STATE_CONNECTED); + Assert.assertEquals( + BluetoothProfile.STATE_DISCONNECTING, mService.getConnectionState(device)); + + LeAudioStackEvent create_event = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); + create_event.device = device; + create_event.valueInt1 = LeAudioStackEvent.CONNECTION_STATE_DISCONNECTED; + mService.messageFromNative(create_event); + + verifyConnectionStateIntent( + TIMEOUT_MS, + device, + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.STATE_DISCONNECTING); + Assert.assertEquals( + BluetoothProfile.STATE_DISCONNECTED, mService.getConnectionState(device)); + mService.deviceDisconnected(device, false); + TestUtils.waitForLooperToFinishScheduledTask(mService.getMainLooper()); + } + + @Test + @EnableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION, + Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP, + Flags.FLAG_LEAUDIO_USE_AUDIO_RECORDING_LISTENER + }) + public void testSetDefaultBroadcastToUnicastFallbackGroup() { + int groupId = 1; + int groupId2 = 2; + int broadcastId = 243; + byte[] code = {0x00, 0x01, 0x00, 0x02}; + List<BluetoothDevice> devices = new ArrayList<>(); + + when(mDatabaseManager.getMostRecentlyConnectedDevices()).thenReturn(devices); + + Assert.assertEquals( + mService.getBroadcastToUnicastFallbackGroup(), LE_AUDIO_GROUP_ID_INVALID); + + initializeNative(); + devices.add(mDevice); + prepareHandoverStreamingBroadcast(groupId, broadcastId, code); + mService.deviceConnected(mDevice); + devices.add(mDevice2); + prepareConnectedUnicastDevice(groupId2, mDevice2); + + LeAudioStackEvent stackEvent = + new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED); + stackEvent.valueInt1 = groupId2; + stackEvent.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE; + mService.messageFromNative(stackEvent); + + /* First connected group become fallback group */ + Assert.assertEquals(mService.mUnicastGroupIdDeactivatedForBroadcastTransition, groupId); + + reset(mAudioManager); + + mService.setBroadcastToUnicastFallbackGroup(groupId2); + + assertThat(mService.getBroadcastToUnicastFallbackGroup()).isEqualTo(groupId2); + + /* Disconnected last device from fallback should trigger set default group 2 -> 1 */ + disconnectDevice(mDevice2); + assertThat(mService.getBroadcastToUnicastFallbackGroup()).isEqualTo(groupId); + stackEvent.valueInt1 = groupId; + mService.messageFromNative(stackEvent); + + /* Disconnected last device from fallback should trigger set default group 1 -> -1 */ + disconnectDevice(mDevice); + assertThat(mService.getBroadcastToUnicastFallbackGroup()) + .isEqualTo(LE_AUDIO_GROUP_ID_INVALID); + } + private BluetoothLeBroadcastSettings buildBroadcastSettingsFromMetadata( BluetoothLeAudioContentMetadata contentMetadata, @Nullable byte[] broadcastCode, diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java index e03a978949..e59230894a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java @@ -77,7 +77,6 @@ import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.hap.HapClientService; import com.android.bluetooth.hfp.HeadsetService; import com.android.bluetooth.le_scan.ScanController; -import com.android.bluetooth.le_scan.TransitionalScanHelper; import com.android.bluetooth.mcp.McpService; import com.android.bluetooth.tbs.TbsService; import com.android.bluetooth.vc.VolumeControlService; @@ -139,7 +138,6 @@ public class LeAudioServiceTest { @Mock private AdapterService mAdapterService; @Mock private GattService mGattService; @Mock private ScanController mScanController; - @Mock private TransitionalScanHelper mTransitionalScanHelper; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AudioManager mAudioManager; @Mock private DatabaseManager mDatabaseManager; @@ -229,7 +227,6 @@ public class LeAudioServiceTest { .getBondedDevices(); doReturn(mGattService).when(mAdapterService).getBluetoothGattService(); doReturn(mScanController).when(mAdapterService).getBluetoothScanController(); - doReturn(mTransitionalScanHelper).when(mScanController).getTransitionalScanHelper(); LeAudioBroadcasterNativeInterface.setInstance(mLeAudioBroadcasterNativeInterface); LeAudioNativeInterface.setInstance(mNativeInterface); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java index 103b5b80f9..3c87186545 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java @@ -17,6 +17,9 @@ package com.android.bluetooth.le_audio; +import static com.android.bluetooth.le_audio.LeAudioStateMachine.CONNECT; +import static com.android.bluetooth.le_audio.LeAudioStateMachine.DISCONNECT; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.after; @@ -34,12 +37,15 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.Bundle; import android.os.HandlerThread; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.flags.Flags; import org.junit.After; import org.junit.Before; @@ -60,6 +66,7 @@ public class LeAudioStateMachineTest { private static final int TIMEOUT_MS = 1000; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private AdapterService mAdapterService; @Mock private LeAudioService mLeAudioService; @@ -232,4 +239,41 @@ public class LeAudioStateMachineTest { assertThat(mLeAudioStateMachine.getCurrentState()) .isInstanceOf(LeAudioStateMachine.Disconnected.class); } + + private void sendAndDispatchMessage(int what, Object obj) { + mLeAudioStateMachine.sendMessage(what, obj); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + } + + @Test + @EnableFlags(Flags.FLAG_LEAUDIO_SM_IGNORE_CONNECT_EVENTS_IN_CONNECTING_STATE) + public void connectEventNeglectedWhileInConnectingState() { + allowConnection(true); + doReturn(true).when(mLeAudioNativeInterface).connectLeAudio(any(BluetoothDevice.class)); + doReturn(true).when(mLeAudioNativeInterface).disconnectLeAudio(any(BluetoothDevice.class)); + + sendAndDispatchMessage(CONNECT, mTestDevice); + // Verify that one connection state change is notified + verify(mLeAudioService, timeout(TIMEOUT_MS)) + .notifyConnectionStateChanged( + any(), + eq(BluetoothProfile.STATE_CONNECTING), + eq(BluetoothProfile.STATE_DISCONNECTED)); + assertThat(mLeAudioStateMachine.getCurrentState()) + .isInstanceOf(LeAudioStateMachine.Connecting.class); + + // Dispatch CONNECT event twice more + sendAndDispatchMessage(CONNECT, mTestDevice); + sendAndDispatchMessage(CONNECT, mTestDevice); + sendAndDispatchMessage(DISCONNECT, mTestDevice); + // Verify that one connection state change is notified + verify(mLeAudioService, timeout(TIMEOUT_MS)) + .notifyConnectionStateChanged( + any(), + eq(BluetoothProfile.STATE_DISCONNECTED), + eq(BluetoothProfile.STATE_CONNECTING)); + assertThat(mLeAudioStateMachine.getCurrentState()) + .isInstanceOf(LeAudioStateMachine.Disconnected.class); + TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); + } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java index 24d8e2c0b5..b442924dae 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java @@ -55,7 +55,7 @@ public class AppScanStatsTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private ScannerMap map; - @Mock private TransitionalScanHelper mMockScanHelper; + @Mock private ScanController mMockScanController; @Mock private AdapterService mAdapterService; // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the @@ -79,10 +79,10 @@ public class AppScanStatsTest { AppScanStats appScanStats = new AppScanStats( - name, source, map, mAdapterService, mMockScanHelper, getSystemClock()); + name, source, map, mAdapterService, mMockScanController, getSystemClock()); assertThat(appScanStats.mScannerMap).isEqualTo(map); - assertThat(appScanStats.mScanHelper).isEqualTo(mMockScanHelper); + assertThat(appScanStats.mScanController).isEqualTo(mMockScanController); assertThat(appScanStats.isScanning()).isEqualTo(false); } @@ -94,7 +94,7 @@ public class AppScanStatsTest { AppScanStats appScanStats = new AppScanStats( - name, source, map, mAdapterService, mMockScanHelper, getSystemClock()); + name, source, map, mAdapterService, mMockScanController, getSystemClock()); ScanSettings settings = new ScanSettings.Builder().build(); List<ScanFilter> filters = new ArrayList<>(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanControllerTest.java index e3db44b86b..2b19c1aa0b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanControllerTest.java @@ -43,7 +43,6 @@ import android.os.Binder; import android.os.RemoteException; import android.os.WorkSource; import android.os.test.TestLooper; -import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.InstrumentationRegistry; @@ -53,7 +52,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.CompanionManager; -import com.android.bluetooth.flags.Flags; import com.android.bluetooth.gatt.GattNativeInterface; import com.android.bluetooth.gatt.GattObjectsFactory; @@ -73,16 +71,16 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -/** Test cases for {@link TransitionalScanHelper}. */ +/** Test cases for {@link ScanController}. */ @SmallTest @RunWith(AndroidJUnit4.class) -public class TransitionalScanHelperTest { +public class ScanControllerTest { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private ScannerMap mScannerMap; @Mock private ScannerMap.ScannerApp mApp; - @Mock private TransitionalScanHelper.PendingIntentInfo mPiInfo; + @Mock private ScanController.PendingIntentInfo mPiInfo; @Mock private PeriodicScanManager mPeriodicScanManager; @Mock private ScanManager mScanManager; @Mock private Resources mResources; @@ -96,7 +94,7 @@ public class TransitionalScanHelperTest { private final AttributionSource mAttributionSource = mAdapter.getAttributionSource(); private final Context mContext = InstrumentationRegistry.getTargetContext(); - private TransitionalScanHelper mScanHelper; + private ScanController mScanController; private CompanionManager mBtCompanionManager; @Before @@ -112,7 +110,7 @@ public class TransitionalScanHelperTest { doReturn(mResources).when(mAdapterService).getResources(); doReturn(mContext.getPackageManager()).when(mAdapterService).getPackageManager(); - doReturn(mContext.getSharedPreferences("TransitionalScanHelperTest", Context.MODE_PRIVATE)) + doReturn(mContext.getSharedPreferences("ScanControllerTest", Context.MODE_PRIVATE)) .when(mAdapterService) .getSharedPreferences(anyString(), anyInt()); @@ -125,15 +123,15 @@ public class TransitionalScanHelperTest { TestLooper testLooper = new TestLooper(); testLooper.startAutoDispatch(); - mScanHelper = new TransitionalScanHelper(mAdapterService, () -> false); - mScanHelper.start(testLooper.getLooper()); + mScanController = new ScanController(mAdapterService); + // mScanController.start(testLooper.getLooper()); - mScanHelper.setScannerMap(mScannerMap); + mScanController.setScannerMap(mScannerMap); } @After public void tearDown() throws Exception { - mScanHelper.stop(); + mScanController.stop(); GattObjectsFactory.setInstanceForTesting(null); ScanObjectsFactory.setInstanceForTesting(null); @@ -141,7 +139,7 @@ public class TransitionalScanHelperTest { @Test public void testParseBatchTimestamp() { - long timestampNanos = mScanHelper.parseTimestampNanos(new byte[] {-54, 7}); + long timestampNanos = mScanController.parseTimestampNanos(new byte[] {-54, 7}); assertThat(timestampNanos).isEqualTo(99700000000L); } @@ -155,7 +153,7 @@ public class TransitionalScanHelperTest { AppScanStats appScanStats = mock(AppScanStats.class); doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId); - mScanHelper.continuePiStartScan(scannerId, mApp); + mScanController.continuePiStartScan(scannerId, mApp); verify(appScanStats) .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId, null); @@ -173,7 +171,7 @@ public class TransitionalScanHelperTest { AppScanStats appScanStats = mock(AppScanStats.class); doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId); - mScanHelper.continuePiStartScan(scannerId, mApp); + mScanController.continuePiStartScan(scannerId, mApp); verify(appScanStats) .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId, null); @@ -208,7 +206,7 @@ public class TransitionalScanHelperTest { doReturn(scanClientSet).when(mScanManager).getFullBatchScanQueue(); doReturn(mApp).when(mScannerMap).getById(scanClient.scannerId); - mScanHelper.onBatchScanReportsInternal( + mScanController.onBatchScanReportsInternal( status, scannerId, reportType, numRecords, recordData); verify(mScanManager).callbackDone(scannerId, status); @@ -221,28 +219,29 @@ public class TransitionalScanHelperTest { IScannerCallback callback = mock(IScannerCallback.class); mApp.mCallback = callback; - mScanHelper.onBatchScanReportsInternal( + mScanController.onBatchScanReportsInternal( status, scannerId, reportType, numRecords, recordData); verify(callback).onBatchScanResults(any()); } @Test public void enforceReportDelayFloor() { - long reportDelayFloorHigher = TransitionalScanHelper.DEFAULT_REPORT_DELAY_FLOOR + 1; + long reportDelayFloorHigher = ScanController.DEFAULT_REPORT_DELAY_FLOOR + 1; ScanSettings scanSettings = new ScanSettings.Builder().setReportDelay(reportDelayFloorHigher).build(); - ScanSettings newScanSettings = mScanHelper.enforceReportDelayFloor(scanSettings); + ScanSettings newScanSettings = mScanController.enforceReportDelayFloor(scanSettings); assertThat(newScanSettings.getReportDelayMillis()) .isEqualTo(scanSettings.getReportDelayMillis()); ScanSettings scanSettingsFloor = new ScanSettings.Builder().setReportDelay(1).build(); - ScanSettings newScanSettingsFloor = mScanHelper.enforceReportDelayFloor(scanSettingsFloor); + ScanSettings newScanSettingsFloor = + mScanController.enforceReportDelayFloor(scanSettingsFloor); assertThat(newScanSettingsFloor.getReportDelayMillis()) - .isEqualTo(TransitionalScanHelper.DEFAULT_REPORT_DELAY_FLOOR); + .isEqualTo(ScanController.DEFAULT_REPORT_DELAY_FLOOR); } @Test @@ -253,7 +252,7 @@ public class TransitionalScanHelperTest { AppScanStats appScanStats = mock(AppScanStats.class); doReturn(appScanStats).when(mScannerMap).getAppScanStatsByUid(Binder.getCallingUid()); - mScanHelper.registerScanner(callback, workSource, mAttributionSource); + mScanController.registerScanner(callback, workSource, mAttributionSource); verify(mScannerMap) .add( any(), @@ -261,7 +260,7 @@ public class TransitionalScanHelperTest { eq(workSource), eq(callback), any(), - eq(mScanHelper)); + eq(mScanController)); verify(mScanManager).registerScanner(any()); } @@ -269,7 +268,7 @@ public class TransitionalScanHelperTest { public void flushPendingBatchResults() { int scannerId = 3; - mScanHelper.flushPendingBatchResults(scannerId, mAttributionSource); + mScanController.flushPendingBatchResults(scannerId, mAttributionSource); verify(mScanManager).flushBatchScanResults(new ScanClient(scannerId)); } @@ -313,7 +312,7 @@ public class TransitionalScanHelperTest { // Simulate remote client crash doThrow(new RemoteException()).when(callback).onScanResult(any()); - mScanHelper.onScanResult( + mScanController.onScanResult( eventType, addressType, address, @@ -337,7 +336,7 @@ public class TransitionalScanHelperTest { int timeout = 2; IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); - mScanHelper.registerSync(scanResult, skip, timeout, callback, mAttributionSource); + mScanController.registerSync(scanResult, skip, timeout, callback, mAttributionSource); verify(mPeriodicScanManager).startSync(scanResult, skip, timeout, callback); } @@ -346,7 +345,7 @@ public class TransitionalScanHelperTest { int serviceData = 1; int syncHandle = 2; - mScanHelper.transferSync(mDevice, serviceData, syncHandle, mAttributionSource); + mScanController.transferSync(mDevice, serviceData, syncHandle, mAttributionSource); verify(mPeriodicScanManager).transferSync(mDevice, serviceData, syncHandle); } @@ -356,7 +355,8 @@ public class TransitionalScanHelperTest { int advHandle = 2; IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); - mScanHelper.transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource); + mScanController.transferSetInfo( + mDevice, serviceData, advHandle, callback, mAttributionSource); verify(mPeriodicScanManager).transferSetInfo(mDevice, serviceData, advHandle, callback); } @@ -364,24 +364,13 @@ public class TransitionalScanHelperTest { public void unregisterSync() { IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); - mScanHelper.unregisterSync(callback, mAttributionSource); + mScanController.unregisterSync(callback, mAttributionSource); verify(mPeriodicScanManager).stopSync(callback); } @Test - public void getCurrentUsedTrackingAdvertisement() { - mScanHelper.getCurrentUsedTrackingAdvertisement(); - verify(mScanManager).getCurrentUsedTrackingAdvertisement(); - } - - @Test - public void cleanUp_doesNotCrash() { - mScanHelper.cleanup(); - } - - @Test public void profileConnectionStateChanged_notifyScanManager() { - mScanHelper.notifyProfileConnectionStateChange( + mScanController.notifyProfileConnectionStateChange( BluetoothProfile.A2DP, BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED); @@ -401,7 +390,7 @@ public class TransitionalScanHelperTest { byte[] scanRsp = new byte[] {0x04}; int filtIndex = 5; - int advState = TransitionalScanHelper.ADVT_STATE_ONFOUND; + int advState = ScanController.ADVT_STATE_ONFOUND; int advInfoPresent = 7; String address = "00:11:22:33:FF:EE"; int addrType = BluetoothDevice.ADDRESS_TYPE_RANDOM; @@ -422,7 +411,7 @@ public class TransitionalScanHelperTest { IScannerCallback callback = mock(IScannerCallback.class); app.mCallback = callback; - app.mInfo = mock(TransitionalScanHelper.PendingIntentInfo.class); + app.mInfo = mock(ScanController.PendingIntentInfo.class); doReturn(app).when(mScannerMap).getById(scannerId); doReturn(scanClientSet).when(mScanManager).getRegularScanQueue(); @@ -443,7 +432,7 @@ public class TransitionalScanHelperTest { rssiValue, timeStamp); - mScanHelper.onTrackAdvFoundLost(advtFilterOnFoundOnLostInfo); + mScanController.onTrackAdvFoundLost(advtFilterOnFoundOnLostInfo); ArgumentCaptor<ScanResult> result = ArgumentCaptor.forClass(ScanResult.class); verify(callback).onFoundOrLost(eq(true), result.capture()); assertThat(result.getValue().getDevice()).isNotNull(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java index e0f908d70b..25a27ce876 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java @@ -126,7 +126,7 @@ public class ScanManagerTest { @Mock private LocationManager mLocationManager; @Mock private MetricsLogger mMetricsLogger; @Mock private ScanNativeInterface mScanNativeInterface; - @Mock private TransitionalScanHelper mScanHelper; + @Mock private ScanController mScanController; @Spy private GattObjectsFactory mGattObjectsFactory = GattObjectsFactory.getInstance(); @Spy private ScanObjectsFactory mScanObjectsFactory = ScanObjectsFactory.getInstance(); @@ -238,7 +238,7 @@ public class ScanManagerTest { mScanManager = new ScanManager( mAdapterService, - mScanHelper, + mScanController, mBluetoothAdapterProxy, mLooper.getLooper(), mTimeProvider); @@ -251,7 +251,7 @@ public class ScanManagerTest { null, null, mAdapterService, - mScanHelper, + mScanController, mTimeProvider)); } @@ -1257,7 +1257,7 @@ public class ScanManagerTest { source, null, mAdapterService, - mScanHelper, + mScanController, mTimeProvider)); // Create scan client for the app, which also records scan start ScanClient client = createScanClient(isFiltered, scanMode, UID, appScanStats); @@ -1328,7 +1328,7 @@ public class ScanManagerTest { source1, null, mAdapterService, - mScanHelper, + mScanController, mTimeProvider)); // Create scan client for the first app ScanClient client1 = @@ -1350,7 +1350,7 @@ public class ScanManagerTest { source2, null, mAdapterService, - mScanHelper, + mScanController, mTimeProvider)); // Create scan client for the second app ScanClient client2 = createScanClient(isFiltered, SCAN_MODE_BALANCED, UID_2, appScanStats2); @@ -1386,7 +1386,7 @@ public class ScanManagerTest { source3, null, mAdapterService, - mScanHelper, + mScanController, mTimeProvider)); // Create scan client for the third app ScanClient client3 = @@ -1423,7 +1423,7 @@ public class ScanManagerTest { source4, null, mAdapterService, - mScanHelper, + mScanController, mTimeProvider)); // Create scan client for the fourth app ScanClient client4 = @@ -1909,7 +1909,7 @@ public class ScanManagerTest { mScanManager = new ScanManager( mAdapterService, - mScanHelper, + mScanController, mBluetoothAdapterProxy, mLooper.getLooper(), mTimeProvider); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java index 83cdcceae9..b8ad36f891 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java @@ -61,7 +61,7 @@ public class ScannerMapTest { @Mock private AdapterService mAdapterService; @Mock private PackageManager mMockPackageManager; - @Mock private TransitionalScanHelper mMockTransitionalScanHelper; + @Mock private ScanController mMockScanController; @Mock private IScannerCallback mMockScannerCallback; private final AttributionSource mAttributionSource = InstrumentationRegistry.getTargetContext().getAttributionSource(); @@ -85,8 +85,7 @@ public class ScannerMapTest { @Test public void getByMethodsWithPii() { ScannerMap scannerMap = new ScannerMap(); - TransitionalScanHelper.PendingIntentInfo info = - new TransitionalScanHelper.PendingIntentInfo(); + ScanController.PendingIntentInfo info = new ScanController.PendingIntentInfo(); info.callingUid = UID; info.callingPackage = APP_NAME; info.intent = @@ -98,11 +97,7 @@ public class ScannerMapTest { UUID uuid = UUID.randomUUID(); ScannerMap.ScannerApp app = scannerMap.add( - uuid, - mAttributionSource, - info, - mAdapterService, - mMockTransitionalScanHelper); + uuid, mAttributionSource, info, mAdapterService, mMockScanController); app.mId = SCANNER_ID; ScannerMap.ScannerApp scannerMapById = scannerMap.getById(SCANNER_ID); @@ -132,7 +127,7 @@ public class ScannerMapTest { null, mMockScannerCallback, mAdapterService, - mMockTransitionalScanHelper); + mMockScanController); int appUid = Binder.getCallingUid(); app.mId = SCANNER_ID; @@ -161,7 +156,7 @@ public class ScannerMapTest { null, mMockScannerCallback, mAdapterService, - mMockTransitionalScanHelper); + mMockScanController); app.mId = SCANNER_ID; ScannerMap.ScannerApp scannerMapById = scannerMap.getById(SCANNER_ID); @@ -181,7 +176,7 @@ public class ScannerMapTest { null, mMockScannerCallback, mAdapterService, - mMockTransitionalScanHelper); + mMockScanController); scannerMap.dump(sb); scannerMap.dumpApps(sb, ProfileService::println); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java index 4993b863a6..8e1be7da7f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java @@ -202,7 +202,7 @@ public class BluetoothMapAccountItemTest { TEST_UCI, TEST_UCI_PREFIX); - assertThat(accountItem).isNotEqualTo(null); + assertThat(accountItem).isNotNull(); } @SuppressWarnings("EqualsIncompatibleType") diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java index 316dd5f621..03aa0e24e1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java @@ -55,7 +55,6 @@ import com.android.obex.ResponseCodes; import com.google.android.mms.pdu.PduHeaders; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -233,9 +232,9 @@ public class BluetoothMapContentObserverTest { () -> observer.pushMessage(message, folderElement, appParams, null)); // Validate that 3 addresses were inserted into the database with 2 being the recipients - Assert.assertEquals(3, mProvider.mContents.size()); - assertThat(mProvider.mContents.contains(TEST_NUMBER_ONE)).isTrue(); - assertThat(mProvider.mContents.contains(TEST_NUMBER_TWO)).isTrue(); + assertThat(mProvider.mContents.size()).isEqualTo(3); + assertThat(mProvider.mContents).contains(TEST_NUMBER_ONE); + assertThat(mProvider.mContents).contains(TEST_NUMBER_TWO); } @Test @@ -305,47 +304,40 @@ public class BluetoothMapContentObserverTest { @Test public void testSetContactList() { - Map<String, BluetoothMapConvoContactElement> map = Map.of(); + mObserver.setContactList(Map.of(), true); - mObserver.setContactList(map, true); - - Assert.assertEquals(mObserver.getContactList(), map); + assertThat(mObserver.getContactList()).isEmpty(); } @Test public void testSetMsgListSms() { - Map<Long, BluetoothMapContentObserver.Msg> map = Map.of(); - - mObserver.setMsgListSms(map, true); + mObserver.setMsgListSms(Map.of(), true); - Assert.assertEquals(mObserver.getMsgListSms(), map); + assertThat(mObserver.getMsgListSms()).isEmpty(); } @Test public void testSetMsgListMsg() { - Map<Long, BluetoothMapContentObserver.Msg> map = Map.of(); + mObserver.setMsgListMsg(Map.of(), true); - mObserver.setMsgListMsg(map, true); - - Assert.assertEquals(mObserver.getMsgListMsg(), map); + assertThat(mObserver.getMsgListMsg()).isEmpty(); } @Test public void testSetMsgListMms() { - Map<Long, BluetoothMapContentObserver.Msg> map = Map.of(); + mObserver.setMsgListMms(Map.of(), true); - mObserver.setMsgListMms(map, true); - - Assert.assertEquals(mObserver.getMsgListMms(), map); + assertThat(mObserver.getMsgListMms()).isEmpty(); } @Test public void testSetNotificationRegistration_withNullHandler() throws Exception { when(mClient.getMessageHandler()).thenReturn(null); - Assert.assertEquals( - mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO), - ResponseCodes.OBEX_HTTP_UNAVAILABLE); + assertThat( + mObserver.setNotificationRegistration( + BluetoothMapAppParams.NOTIFICATION_STATUS_NO)) + .isEqualTo(ResponseCodes.OBEX_HTTP_UNAVAILABLE); } @Test @@ -357,9 +349,10 @@ public class BluetoothMapContentObserverTest { when(mClient.getMessageHandler()).thenReturn(handler); when(mClient.isValidMnsRecord()).thenReturn(false); - Assert.assertEquals( - mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO), - ResponseCodes.OBEX_HTTP_OK); + assertThat( + mObserver.setNotificationRegistration( + BluetoothMapAppParams.NOTIFICATION_STATUS_NO)) + .isEqualTo(ResponseCodes.OBEX_HTTP_OK); } @Test @@ -371,9 +364,10 @@ public class BluetoothMapContentObserverTest { when(mClient.getMessageHandler()).thenReturn(handler); when(mClient.isValidMnsRecord()).thenReturn(true); - Assert.assertEquals( - mObserver.setNotificationRegistration(BluetoothMapAppParams.NOTIFICATION_STATUS_NO), - ResponseCodes.OBEX_HTTP_OK); + assertThat( + mObserver.setNotificationRegistration( + BluetoothMapAppParams.NOTIFICATION_STATUS_NO)) + .isEqualTo(ResponseCodes.OBEX_HTTP_OK); } @Test @@ -392,7 +386,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, type, TEST_URI_STR, TEST_STATUS_VALUE)) .isTrue(); - Assert.assertEquals(msg.flagRead, TEST_STATUS_VALUE); + assertThat(msg.flagRead).isEqualTo(TEST_STATUS_VALUE); } @Test @@ -411,7 +405,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, type, TEST_URI_STR, TEST_STATUS_VALUE)) .isTrue(); - Assert.assertEquals(msg.flagRead, TEST_STATUS_VALUE); + assertThat(msg.flagRead).isEqualTo(TEST_STATUS_VALUE); } @Test @@ -429,7 +423,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, type, TEST_URI_STR, TEST_STATUS_VALUE)) .isTrue(); - Assert.assertEquals(msg.flagRead, TEST_STATUS_VALUE); + assertThat(msg.flagRead).isEqualTo(TEST_STATUS_VALUE); } @Test @@ -439,7 +433,7 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListMms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); MatrixCursor cursor = new MatrixCursor(new String[] {Mms.THREAD_ID}); cursor.addRow(new Object[] {TEST_THREAD_ID}); @@ -452,7 +446,7 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.deleteMessageMms(TEST_HANDLE_ONE)).isTrue(); - Assert.assertEquals(msg.threadId, BluetoothMapContentObserver.DELETED_THREAD_ID); + assertThat(msg.threadId).isEqualTo(BluetoothMapContentObserver.DELETED_THREAD_ID); } @Test @@ -485,7 +479,7 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListSms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); MatrixCursor cursor = new MatrixCursor(new String[] {Mms.THREAD_ID}); cursor.addRow(new Object[] {TEST_THREAD_ID}); @@ -498,7 +492,7 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.deleteMessageSms(TEST_HANDLE_ONE)).isTrue(); - Assert.assertEquals(msg.threadId, BluetoothMapContentObserver.DELETED_THREAD_ID); + assertThat(msg.threadId).isEqualTo(BluetoothMapContentObserver.DELETED_THREAD_ID); } @Test @@ -531,8 +525,8 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListMms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Mms.MESSAGE_BOX_ALL); MatrixCursor cursor = new MatrixCursor( @@ -556,8 +550,8 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.unDeleteMessageMms(TEST_HANDLE_ONE)).isTrue(); - Assert.assertEquals(msg.threadId, TEST_OLD_THREAD_ID); - Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_INBOX); + assertThat(msg.threadId).isEqualTo(TEST_OLD_THREAD_ID); + assertThat(msg.type).isEqualTo(Mms.MESSAGE_BOX_INBOX); } @Test @@ -567,8 +561,8 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListMms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Mms.MESSAGE_BOX_ALL); MatrixCursor cursor = new MatrixCursor( @@ -592,8 +586,8 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.unDeleteMessageMms(TEST_HANDLE_ONE)).isTrue(); - Assert.assertEquals(msg.threadId, TEST_OLD_THREAD_ID); - Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_INBOX); + assertThat(msg.threadId).isEqualTo(TEST_OLD_THREAD_ID); + assertThat(msg.type).isEqualTo(Mms.MESSAGE_BOX_INBOX); } @Test @@ -603,8 +597,8 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Mms.MESSAGE_BOX_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListMms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Mms.MESSAGE_BOX_ALL); MatrixCursor cursor = new MatrixCursor( @@ -622,8 +616,8 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.unDeleteMessageMms(TEST_HANDLE_ONE)).isTrue(); // Nothing changes when thread id is not BluetoothMapContentObserver.DELETED_THREAD_ID - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Sms.MESSAGE_TYPE_ALL); } @Test @@ -633,8 +627,8 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListSms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Sms.MESSAGE_TYPE_ALL); MatrixCursor cursor = new MatrixCursor(new String[] {Sms.THREAD_ID, Sms.ADDRESS}); cursor.addRow(new Object[] {BluetoothMapContentObserver.DELETED_THREAD_ID, TEST_ADDRESS}); @@ -650,8 +644,8 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.unDeleteMessageSms(TEST_HANDLE_ONE)).isTrue(); - Assert.assertEquals(msg.threadId, TEST_OLD_THREAD_ID); - Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_INBOX); + assertThat(msg.threadId).isEqualTo(TEST_OLD_THREAD_ID); + assertThat(msg.type).isEqualTo(Sms.MESSAGE_TYPE_INBOX); } @Test @@ -661,8 +655,8 @@ public class BluetoothMapContentObserverTest { createMsgWithTypeAndThreadId(Sms.MESSAGE_TYPE_ALL, TEST_THREAD_ID); map.put(TEST_HANDLE_ONE, msg); mObserver.setMsgListSms(map, true); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Sms.MESSAGE_TYPE_ALL); MatrixCursor cursor = new MatrixCursor(new String[] {Sms.THREAD_ID, Sms.ADDRESS}); cursor.addRow(new Object[] {TEST_THREAD_ID, TEST_ADDRESS}); @@ -676,8 +670,8 @@ public class BluetoothMapContentObserverTest { assertThat(mObserver.unDeleteMessageSms(TEST_HANDLE_ONE)).isTrue(); // Nothing changes when thread id is not BluetoothMapContentObserver.DELETED_THREAD_ID - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.type, Sms.MESSAGE_TYPE_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.type).isEqualTo(Sms.MESSAGE_TYPE_ALL); } @Test @@ -691,11 +685,11 @@ public class BluetoothMapContentObserverTest { BluetoothMapContentObserver.PushMsgInfo msgInfo = new BluetoothMapContentObserver.PushMsgInfo(id, transparent, retry, phone, uri); - Assert.assertEquals(msgInfo.id, id); - Assert.assertEquals(msgInfo.transparent, transparent); - Assert.assertEquals(msgInfo.retry, retry); - Assert.assertEquals(msgInfo.phone, phone); - Assert.assertEquals(msgInfo.uri, uri); + assertThat(msgInfo.id).isEqualTo(id); + assertThat(msgInfo.transparent).isEqualTo(transparent); + assertThat(msgInfo.retry).isEqualTo(retry); + assertThat(msgInfo.phone).isEqualTo(phone); + assertThat(msgInfo.uri).isEqualTo(uri); } @Test @@ -719,7 +713,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, BluetoothMapAppParams.STATUS_VALUE_YES)) .isTrue(); - Assert.assertEquals(msg.folderId, TEST_DELETE_FOLDER_ID); + assertThat(msg.folderId).isEqualTo(TEST_DELETE_FOLDER_ID); } @Test @@ -768,7 +762,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, BluetoothMapAppParams.STATUS_VALUE_NO)) .isTrue(); - Assert.assertEquals(msg.folderId, TEST_INBOX_FOLDER_ID); + assertThat(msg.folderId).isEqualTo(TEST_INBOX_FOLDER_ID); } @Test @@ -797,7 +791,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, BluetoothMapAppParams.STATUS_VALUE_NO)) .isTrue(); - Assert.assertEquals(msg.folderId, TEST_INBOX_FOLDER_ID); + assertThat(msg.folderId).isEqualTo(TEST_INBOX_FOLDER_ID); } @Test @@ -828,7 +822,7 @@ public class BluetoothMapContentObserverTest { TEST_HANDLE_ONE, BluetoothMapAppParams.STATUS_VALUE_NO)) .isTrue(); - Assert.assertEquals(msg.folderId, TEST_OLD_FOLDER_ID); + assertThat(msg.folderId).isEqualTo(TEST_OLD_FOLDER_ID); } @Test @@ -949,10 +943,10 @@ public class BluetoothMapContentObserverTest { mObserver.initMsgList(); BluetoothMapContentObserver.Msg msg = mObserver.getMsgListSms().get((long) TEST_ID); - Assert.assertEquals(msg.id, TEST_ID); - Assert.assertEquals(msg.type, TEST_SMS_TYPE_ALL); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.flagRead, TEST_READ_FLAG_ONE); + assertThat(msg.id).isEqualTo(TEST_ID); + assertThat(msg.type).isEqualTo(TEST_SMS_TYPE_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.flagRead).isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -988,10 +982,10 @@ public class BluetoothMapContentObserverTest { mObserver.initMsgList(); BluetoothMapContentObserver.Msg msg = mObserver.getMsgListMms().get((long) TEST_ID); - Assert.assertEquals(msg.id, TEST_ID); - Assert.assertEquals(msg.type, TEST_MMS_TYPE_ALL); - Assert.assertEquals(msg.threadId, TEST_THREAD_ID); - Assert.assertEquals(msg.flagRead, TEST_READ_FLAG_ZERO); + assertThat(msg.id).isEqualTo(TEST_ID); + assertThat(msg.type).isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(msg.threadId).isEqualTo(TEST_THREAD_ID); + assertThat(msg.flagRead).isEqualTo(TEST_READ_FLAG_ZERO); } @Test @@ -1028,9 +1022,9 @@ public class BluetoothMapContentObserverTest { mObserver.initMsgList(); BluetoothMapContentObserver.Msg msg = mObserver.getMsgListMsg().get((long) TEST_ID); - Assert.assertEquals(msg.id, TEST_ID); - Assert.assertEquals(msg.folderId, TEST_INBOX_FOLDER_ID); - Assert.assertEquals(msg.flagRead, TEST_READ_FLAG_ONE); + assertThat(msg.id).isEqualTo(TEST_ID); + assertThat(msg.folderId).isEqualTo(TEST_INBOX_FOLDER_ID); + assertThat(msg.flagRead).isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1077,16 +1071,16 @@ public class BluetoothMapContentObserverTest { BluetoothMapConvoContactElement contactElement = mObserver.getContactList().get(TEST_UCI); final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); - Assert.assertEquals(contactElement.getContactId(), TEST_UCI); - Assert.assertEquals(contactElement.getName(), TEST_NAME); - Assert.assertEquals(contactElement.getDisplayName(), TEST_DISPLAY_NAME); - Assert.assertEquals(contactElement.getBtUid(), TEST_BT_UID); - Assert.assertEquals(contactElement.getChatState(), TEST_CHAT_STATE); - Assert.assertEquals(contactElement.getPresenceStatus(), TEST_STATUS_TEXT); - Assert.assertEquals(contactElement.getPresenceAvailability(), TEST_PRESENCE_STATE); - Assert.assertEquals( - contactElement.getLastActivityString(), format.format(TEST_LAST_ACTIVITY)); - Assert.assertEquals(contactElement.getPriority(), TEST_PRIORITY); + assertThat(contactElement.getContactId()).isEqualTo(TEST_UCI); + assertThat(contactElement.getName()).isEqualTo(TEST_NAME); + assertThat(contactElement.getDisplayName()).isEqualTo(TEST_DISPLAY_NAME); + assertThat(contactElement.getBtUid()).isEqualTo(TEST_BT_UID); + assertThat(contactElement.getChatState()).isEqualTo(TEST_CHAT_STATE); + assertThat(contactElement.getPresenceStatus()).isEqualTo(TEST_STATUS_TEXT); + assertThat(contactElement.getPresenceAvailability()).isEqualTo(TEST_PRESENCE_STATE); + assertThat(contactElement.getLastActivityString()) + .isEqualTo(format.format(TEST_LAST_ACTIVITY)); + assertThat(contactElement.getPriority()).isEqualTo(TEST_PRIORITY); } @Test @@ -1130,11 +1124,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type, TEST_INBOX_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_INBOX_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1180,11 +1174,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type, TEST_INBOX_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_INBOX_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1215,11 +1209,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type, TEST_INBOX_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_INBOX_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1250,11 +1244,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_DELETE_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId) + .isEqualTo(TEST_DELETE_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1287,11 +1281,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_SENT_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId) + .isEqualTo(TEST_SENT_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1328,11 +1322,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_SENT_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId) + .isEqualTo(TEST_SENT_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1364,11 +1358,11 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMsg(TEST_URI); - Assert.assertEquals(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId, TEST_INBOX_FOLDER_ID); - Assert.assertEquals( - mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).folderId) + .isEqualTo(TEST_INBOX_FOLDER_ID); + assertThat(mObserver.getMsgListMsg().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1414,12 +1408,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1465,12 +1460,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1521,7 +1517,7 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(null, mObserver.getMsgListMms().get(TEST_HANDLE_ONE)); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE)).isNull(); } @Test @@ -1555,12 +1551,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1595,12 +1592,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1635,12 +1633,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1675,13 +1674,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, - BluetoothMapContentObserver.DELETED_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(BluetoothMapContentObserver.DELETED_THREAD_ID); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1717,12 +1716,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesMms(); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type, TEST_MMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId, undeletedThreadId); - Assert.assertEquals( - mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_MMS_TYPE_ALL); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(undeletedThreadId); + assertThat(mObserver.getMsgListMms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1766,13 +1766,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_INBOX); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_SMS_TYPE_INBOX); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1814,12 +1814,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_SMS_TYPE_ALL); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1865,7 +1866,7 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(null, mObserver.getMsgListSms().get(TEST_HANDLE_ONE)); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE)).isNull(); } @Test @@ -1892,12 +1893,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_SMS_TYPE_ALL); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1924,12 +1926,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, TEST_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_SMS_TYPE_ALL); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(TEST_THREAD_ID); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1959,13 +1962,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, - BluetoothMapContentObserver.DELETED_THREAD_ID); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_SMS_TYPE_ALL); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(BluetoothMapContentObserver.DELETED_THREAD_ID); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -1993,12 +1996,13 @@ public class BluetoothMapContentObserverTest { mObserver.handleMsgListChangesSms(); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id, TEST_HANDLE_ONE); - Assert.assertEquals(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type, TEST_SMS_TYPE_ALL); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId, undeletedThreadId); - Assert.assertEquals( - mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead, TEST_READ_FLAG_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).id).isEqualTo(TEST_HANDLE_ONE); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).type) + .isEqualTo(TEST_SMS_TYPE_ALL); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).threadId) + .isEqualTo(undeletedThreadId); + assertThat(mObserver.getMsgListSms().get(TEST_HANDLE_ONE).flagRead) + .isEqualTo(TEST_READ_FLAG_ONE); } @Test @@ -2074,7 +2078,7 @@ public class BluetoothMapContentObserverTest { mObserver.actionMessageSentDisconnected(mContext, mIntent, 1); - assertThat(mmsMsgList.containsKey(TEST_HANDLE_ONE)).isTrue(); + assertThat(mmsMsgList).containsKey(TEST_HANDLE_ONE); } @Test @@ -2111,7 +2115,7 @@ public class BluetoothMapContentObserverTest { mObserver.actionMmsSent(mContext, mIntent, 1, mmsMsgList); - assertThat(mmsMsgList.containsKey(TEST_HANDLE_ONE)).isTrue(); + assertThat(mmsMsgList).containsKey(TEST_HANDLE_ONE); } @Test @@ -2158,7 +2162,7 @@ public class BluetoothMapContentObserverTest { mObserver.actionMmsSent(mContext, mIntent, Activity.RESULT_OK, mmsMsgList); - assertThat(mmsMsgList.containsKey(TEST_HANDLE_ONE)).isTrue(); + assertThat(mmsMsgList).containsKey(TEST_HANDLE_ONE); } @Test @@ -2176,7 +2180,7 @@ public class BluetoothMapContentObserverTest { mObserver.actionMmsSent(mContext, mIntent, Activity.RESULT_FIRST_USER, mmsMsgList); - Assert.assertEquals(msg.type, Mms.MESSAGE_BOX_OUTBOX); + assertThat(msg.type).isEqualTo(Mms.MESSAGE_BOX_OUTBOX); } @Test @@ -2315,16 +2319,16 @@ public class BluetoothMapContentObserverTest { BluetoothMapConvoContactElement contactElement = mObserver.getContactList().get(TEST_UCI); final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); - Assert.assertEquals(contactElement.getContactId(), TEST_UCI); - Assert.assertEquals(contactElement.getName(), TEST_NAME); - Assert.assertEquals(contactElement.getDisplayName(), TEST_DISPLAY_NAME); - Assert.assertEquals(contactElement.getBtUid(), TEST_BT_UID); - Assert.assertEquals(contactElement.getChatState(), TEST_CHAT_STATE); - Assert.assertEquals(contactElement.getPresenceStatus(), TEST_STATUS_TEXT); - Assert.assertEquals(contactElement.getPresenceAvailability(), TEST_PRESENCE_STATE); - Assert.assertEquals( - contactElement.getLastActivityString(), format.format(TEST_LAST_ACTIVITY)); - Assert.assertEquals(contactElement.getPriority(), TEST_PRIORITY); + assertThat(contactElement.getContactId()).isEqualTo(TEST_UCI); + assertThat(contactElement.getName()).isEqualTo(TEST_NAME); + assertThat(contactElement.getDisplayName()).isEqualTo(TEST_DISPLAY_NAME); + assertThat(contactElement.getBtUid()).isEqualTo(TEST_BT_UID); + assertThat(contactElement.getChatState()).isEqualTo(TEST_CHAT_STATE); + assertThat(contactElement.getPresenceStatus()).isEqualTo(TEST_STATUS_TEXT); + assertThat(contactElement.getPresenceAvailability()).isEqualTo(TEST_PRESENCE_STATE); + assertThat(contactElement.getLastActivityString()) + .isEqualTo(format.format(TEST_LAST_ACTIVITY)); + assertThat(contactElement.getPriority()).isEqualTo(TEST_PRIORITY); } @Test @@ -2386,16 +2390,16 @@ public class BluetoothMapContentObserverTest { BluetoothMapConvoContactElement contactElement = mObserver.getContactList().get(TEST_UCI); final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); - Assert.assertEquals(contactElement.getContactId(), TEST_UCI); - Assert.assertEquals(contactElement.getName(), TEST_NAME); - Assert.assertEquals(contactElement.getDisplayName(), TEST_DISPLAY_NAME); - Assert.assertEquals(contactElement.getBtUid(), TEST_BT_UID); - Assert.assertEquals(contactElement.getChatState(), TEST_CHAT_STATE); - Assert.assertEquals(contactElement.getPresenceStatus(), TEST_STATUS_TEXT); - Assert.assertEquals(contactElement.getPresenceAvailability(), TEST_PRESENCE_STATE); - Assert.assertEquals( - contactElement.getLastActivityString(), format.format(TEST_LAST_ACTIVITY)); - Assert.assertEquals(contactElement.getPriority(), TEST_PRIORITY); + assertThat(contactElement.getContactId()).isEqualTo(TEST_UCI); + assertThat(contactElement.getName()).isEqualTo(TEST_NAME); + assertThat(contactElement.getDisplayName()).isEqualTo(TEST_DISPLAY_NAME); + assertThat(contactElement.getBtUid()).isEqualTo(TEST_BT_UID); + assertThat(contactElement.getChatState()).isEqualTo(TEST_CHAT_STATE); + assertThat(contactElement.getPresenceStatus()).isEqualTo(TEST_STATUS_TEXT); + assertThat(contactElement.getPresenceAvailability()).isEqualTo(TEST_PRESENCE_STATE); + assertThat(contactElement.getLastActivityString()) + .isEqualTo(format.format(TEST_LAST_ACTIVITY)); + assertThat(contactElement.getPriority()).isEqualTo(TEST_PRIORITY); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java index 4f8629f577..cfeba5f602 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java @@ -80,7 +80,7 @@ public class BluetoothMapConvoListingTest { @Test public void segment_whenOffsetIsBiggerThanSize_returnsEmptyList() { mListing.segment(1, 4); - assertThat(mListing.getList().size()).isEqualTo(0); + assertThat(mListing.getList()).isEmpty(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java index 051b131773..c0fca95295 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java @@ -90,7 +90,7 @@ public class BluetoothMapMessageListingTest { @Test public void segment_whenOffsetIsBiggerThanSize_returnsEmptyList() { mListing.segment(1, 4); - assertThat(mListing.getList().size()).isEqualTo(0); + assertThat(mListing.getList()).isEmpty(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java index b929fa65bc..bcf9a266a8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java @@ -137,7 +137,7 @@ public class SmsMmsContactsTest { .when(mMapMethodProxy) .contentResolverQuery(any(), any(), any(), any(), any(), any()); assertThat(mContacts.mNames).isEmpty(); - assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isEqualTo(null); + assertThat(mContacts.getPhoneNumber(mResolver, TEST_ID)).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/BmessageTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/BmessageTest.java index e6716b487c..2366add7d0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/BmessageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/BmessageTest.java @@ -23,7 +23,6 @@ import static org.mockito.Mockito.*; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -96,7 +95,7 @@ public class BmessageTest { message.setCharset("UTF-8"); - Assert.assertEquals(message.getCharset(), "UTF-8"); + assertThat(message.getCharset()).isEqualTo("UTF-8"); } @Test @@ -105,7 +104,7 @@ public class BmessageTest { message.setEncoding("test_encoding"); - Assert.assertEquals(message.getEncoding(), "test_encoding"); + assertThat(message.getEncoding()).isEqualTo("test_encoding"); } @Test @@ -114,6 +113,6 @@ public class BmessageTest { message.setStatus(Bmessage.Status.READ); - Assert.assertEquals(message.getStatus(), Bmessage.Status.READ); + assertThat(message.getStatus()).isEqualTo(Bmessage.Status.READ); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java index 57a0e72941..fc89cca20d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java @@ -51,7 +51,6 @@ import com.android.vcard.VCardEntry; import com.android.vcard.VCardProperty; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -138,7 +137,7 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(0, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues).isEmpty(); } /** Test that a dirty database gets cleaned at startup. */ @@ -153,9 +152,9 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues.size()).isEqualTo(1); mMapClientContent = new MapClientContent(mMockContext, mCallbacks, mTestDevice); - Assert.assertEquals(0, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues).isEmpty(); } /** Test inserting 2 SMS messages and then clearing out the database. */ @@ -170,16 +169,16 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues.size()).isEqualTo(1); mMapClientContent.storeMessage( mTestMessage1, mTestMessage1Handle, mTestMessage1Timestamp, MESSAGE_SEEN); - Assert.assertEquals(2, mMockSmsContentProvider.mContentValues.size()); - Assert.assertEquals(0, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues.size()).isEqualTo(2); + assertThat(mMockMmsContentProvider.mContentValues).isEmpty(); mMapClientContent.cleanUp(); - Assert.assertEquals(0, mMockSmsContentProvider.mContentValues.size()); - Assert.assertEquals(0, mMockThreadContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues).isEmpty(); + assertThat(mMockThreadContentProvider.mContentValues).isEmpty(); } /** Test inserting 2 MMS messages and then clearing out the database. */ @@ -194,14 +193,14 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(1); mMapClientContent.storeMessage( mTestMessage2, mTestMessage1Handle, mTestMessage1Timestamp, MESSAGE_SEEN); - Assert.assertEquals(2, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(2); mMapClientContent.cleanUp(); - Assert.assertEquals(0, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues).isEmpty(); } /** Test that SMS and MMS messages end up in their respective databases. */ @@ -216,14 +215,14 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(1); mMapClientContent.storeMessage( mTestMessage2, mTestMessage2Handle, mTestMessage1Timestamp, MESSAGE_SEEN); - Assert.assertEquals(2, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(2); mMapClientContent.cleanUp(); - Assert.assertEquals(0, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues).isEmpty(); } /** Test read status changed */ @@ -238,16 +237,16 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(1); mMapClientContent.storeMessage( mTestMessage2, mTestMessage1Handle, mTestMessage1Timestamp, MESSAGE_SEEN); - Assert.assertEquals(2, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(2); mMapClientContent.markRead(mTestMessage1Handle); mMapClientContent.cleanUp(); - Assert.assertEquals(0, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues).isEmpty(); } /** @@ -262,7 +261,7 @@ public class MapClientContentTest { mMapClientContent = new MapClientContent(mMockContext, mCallbacks, mTestDevice); mMapClientContent.storeMessage( mTestMessage2, mTestMessage1Handle, mTestMessage1Timestamp, MESSAGE_SEEN); - Assert.assertEquals(1, mMockMmsContentProvider.mContentValues.size()); + assertThat(mMockMmsContentProvider.mContentValues.size()).isEqualTo(1); mMapClientContent.mContentObserver.onChange(false); verify(mCallbacks) .onMessageStatusChanged(eq(mTestMessage1Handle), eq(BluetoothMapClient.READ)); @@ -341,14 +340,14 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues.size()).isEqualTo(1); // attempt to delete an invalid handle, nothing should be removed. mMapClientContent.deleteMessage(mTestMessage2Handle); - Assert.assertEquals(1, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues.size()).isEqualTo(1); // delete a valid handle mMapClientContent.deleteMessage(mTestMessage1Handle); - Assert.assertEquals(0, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues).isEmpty(); } /** @@ -368,7 +367,7 @@ public class MapClientContentTest { any(), anyInt(), eq(SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM)); - Assert.assertEquals(1, mMockSmsContentProvider.mContentValues.size()); + assertThat(mMockSmsContentProvider.mContentValues.size()).isEqualTo(1); mMockSmsContentProvider.mContentValues.clear(); mMapClientContent.mContentObserver.onChange(false); verify(mCallbacks) diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java index b327a6b5f7..0a757e1d07 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java @@ -37,7 +37,6 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; -import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; @@ -92,7 +91,6 @@ public class MapClientServiceTest { mService = MapClientService.getMapClientService(); assertThat(mService).isNull(); TestUtils.clearAdapterService(mAdapterService); - BluetoothMethodProxy.setInstanceForTesting(null); mTestLooper.dispatchAll(); } @@ -256,31 +254,19 @@ public class MapClientServiceTest { } @Test - public void disconnect_doesNotCleanUpNewStateMachineOfSameDevice() { - int connectionPolicy = BluetoothProfile.CONNECTION_POLICY_ALLOWED; - when(mDatabaseManager.getProfileConnectionPolicy( - mRemoteDevice, BluetoothProfile.MAP_CLIENT)) - .thenReturn(connectionPolicy); - - mService.connect(mRemoteDevice); - MceStateMachine connectedSm = mService.getInstanceMap().get(mRemoteDevice); - assertThat(connectedSm).isNotNull(); + public void cleanUpDevice_deviceExistsWithDifferentStateMachine_doesNotCleanUpDevice() { + MceStateMachine sm1 = mock(MceStateMachine.class); + MceStateMachine sm2 = mock(MceStateMachine.class); - connectedSm.sendMessage(MceStateMachine.MSG_MAS_SDP_DONE, mock(SdpMasRecord.class)); - connectedSm.sendMessage(MceStateMachine.MSG_MAS_CONNECTED); - // Stay it connected - while (mTestLooper.isIdle() && connectedSm.getState() != BluetoothProfile.STATE_CONNECTED) { - mTestLooper.dispatchNext(); - } + // Add device as state machine 1 + mService.getInstanceMap().put(mRemoteDevice, sm1); - MceStateMachine sm = mock(MceStateMachine.class); - mService.getInstanceMap().put(mRemoteDevice, sm); - - connectedSm.disconnect(); - mTestLooper.dispatchAll(); - assertThat(connectedSm.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + // Remove device as state machine 2 + mService.cleanupDevice(mRemoteDevice, sm2); + // Device and state machine1 should still be there assertThat(mService.getInstanceMap()).containsKey(mRemoteDevice); + assertThat(mService.getInstanceMap().get(mRemoteDevice)).isEqualTo(sm1); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java index 5d4207faa5..109b7ab82a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java @@ -16,10 +16,25 @@ package com.android.bluetooth.mapclient; +import static android.Manifest.permission.BLUETOOTH_CONNECT; +import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE; +import static android.bluetooth.BluetoothProfile.EXTRA_STATE; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; + +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasPackage; + import static com.google.common.truth.Truth.assertThat; +import static org.hamcrest.Matchers.nullValue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; +import static org.mockito.Mockito.inOrder; import android.app.Activity; import android.app.BroadcastOptions; @@ -27,7 +42,6 @@ import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothMapClient; -import android.bluetooth.BluetoothProfile; import android.bluetooth.SdpMasRecord; import android.content.BroadcastReceiver; import android.content.ContentValues; @@ -36,15 +50,12 @@ import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; +import android.os.test.TestLooper; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.FlagsParameterization; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Telephony.Sms; import android.telephony.SmsManager; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; @@ -55,9 +66,7 @@ import androidx.test.filters.MediumTest; import androidx.test.rule.ServiceTestRule; import com.android.bluetooth.ObexAppParameters; -import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; import com.android.obex.HeaderSet; import com.android.vcard.VCardConstants; @@ -66,15 +75,18 @@ import com.android.vcard.VCardProperty; import com.google.common.truth.Correspondence; +import org.hamcrest.Matcher; +import org.hamcrest.core.AllOf; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.hamcrest.MockitoHamcrest; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -92,26 +104,24 @@ import java.util.concurrent.TimeUnit; @MediumTest @RunWith(ParameterizedAndroidJunit4.class) public class MapClientStateMachineTest { - - private static final String TAG = "MapStateMachineTest"; - @Rule public final SetFlagsRule mSetFlagsRule; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); - private static final int ASYNC_CALL_TIMEOUT_MILLIS = 100; - private static final int DISCONNECT_TIMEOUT = 3000; + @Mock private AdapterService mAdapterService; + @Mock private MapClientService mService; + @Mock private MapClientContent mDatabase; + @Mock private TelephonyManager mTelephonyManager; + @Mock private MasClient mMasClient; + @Mock private RequestPushMessage mRequestPushMessage; + @Mock private RequestGetMessagesListingForOwnNumber mRequestOwnNumberCompletedWithNumber; + @Mock private RequestGetMessagesListingForOwnNumber mRequestOwnNumberIncompleteSearch; + @Mock private RequestGetMessage mRequestGetMessage; + @Mock private RequestGetMessagesListing mRequestGetMessagesListing; + + private static final String TAG = "MapClientStateMachineTest"; private static final long PENDING_INTENT_TIMEOUT_MS = 3_000; - - private static final int CONNECTION_STATE_UNDEFINED = -1; - - private Bmessage mTestIncomingSmsBmessage; - private Bmessage mTestIncomingMmsBmessage; - private String mTestMessageSmsHandle = "0001"; - private String mTestMessageMmsHandle = "0002"; - private String mTestMessageUnknownHandle = "0003"; - boolean mIsAdapterServiceSet; - boolean mIsMapClientServiceStarted; - private static final boolean MESSAGE_SEEN = true; private static final boolean MESSAGE_NOT_SEEN = false; @@ -120,50 +130,29 @@ public class MapClientStateMachineTest { private static final String SENT_PATH = "telecom/msg/sent"; private static final Uri[] TEST_CONTACTS_ONE_PHONENUM = new Uri[] {Uri.parse("tel://5551234")}; private static final String TEST_DATETIME = "19991231T235959"; - - private VCardEntry mOriginator; - - @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); - private BluetoothAdapter mAdapter; - private MceStateMachine mMceStateMachine = null; - private BluetoothDevice mTestDevice; - private Context mTargetContext; - private Handler mHandler; - private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class); - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock private AdapterService mAdapterService; - @Mock private DatabaseManager mDatabaseManager; - @Mock private MapClientService mMockMapClientService; - @Mock private MapClientContent mMockDatabase; - private MockContentResolver mMockContentResolver; - private MockSmsContentProvider mMockContentProvider; - - @Mock private TelephonyManager mMockTelephonyManager; - - @Mock private MasClient mMockMasClient; - - @Mock private RequestPushMessage mMockRequestPushMessage; - - @Mock private SubscriptionManager mMockSubscriptionManager; - private static final String TEST_OWN_PHONE_NUMBER = "555-1234"; - @Mock private RequestGetMessagesListingForOwnNumber mMockRequestOwnNumberCompletedWithNumber; - @Mock private RequestGetMessagesListingForOwnNumber mMockRequestOwnNumberIncompleteSearch; - @Mock private RequestGetMessage mMockRequestGetMessage; - @Mock private RequestGetMessagesListing mMockRequestGetMessagesListing; - private static final Correspondence<Request, String> GET_FOLDER_NAME = Correspondence.transforming( MapClientStateMachineTest::getFolderNameFromRequestGetMessagesListing, "has folder name of"); - private static final String ACTION_MESSAGE_SENT = "com.android.bluetooth.mapclient.MapClientStateMachineTest.action.MESSAGE_SENT"; private static final String ACTION_MESSAGE_DELIVERED = "com.android.bluetooth.mapclient.MapClientStateMachineTest.action.MESSAGE_DELIVERED"; + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); + private final Context mTargetContext = InstrumentationRegistry.getTargetContext(); + private final String mTestMessageSmsHandle = "0001"; + private final String mTestMessageMmsHandle = "0002"; + private final String mTestMessageUnknownHandle = "0003"; + + private Bmessage mTestIncomingSmsBmessage; + private Bmessage mTestIncomingMmsBmessage; + private MceStateMachine mStateMachine; private SentDeliveryReceiver mSentDeliveryReceiver; + private TestLooper mLooper; + private InOrder mInOrder; private static class SentDeliveryReceiver extends BroadcastReceiver { private CountDownLatch mActionReceivedLatch; @@ -207,57 +196,45 @@ public class MapClientStateMachineTest { @Before public void setUp() throws Exception { - mTargetContext = InstrumentationRegistry.getTargetContext(); - TestUtils.setAdapterService(mAdapterService); - mIsAdapterServiceSet = true; - mMockContentProvider = new MockSmsContentProvider(); - mMockContentResolver = new MockContentResolver(); - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); - mIsMapClientServiceStarted = true; - mMockContentResolver.addProvider("sms", mMockContentProvider); - mMockContentResolver.addProvider("mms", mMockContentProvider); - mMockContentResolver.addProvider("mms-sms", mMockContentProvider); - - when(mMockMapClientService.getContentResolver()).thenReturn(mMockContentResolver); - when(mMockMapClientService.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) - .thenReturn(mMockSubscriptionManager); - when(mMockMapClientService.getSystemServiceName(SubscriptionManager.class)) - .thenReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE); - - doReturn(mTargetContext.getResources()).when(mMockMapClientService).getResources(); - - // This line must be called to make sure relevant objects are initialized properly - mAdapter = BluetoothAdapter.getDefaultAdapter(); - // Get a device for testing - mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05"); - - when(mMockMasClient.makeRequest(any(Request.class))).thenReturn(true); - mMceStateMachine = - new MceStateMachine( - mMockMapClientService, mTestDevice, mMockMasClient, mMockDatabase); - TestUtils.waitForLooperToFinishScheduledTask(mMceStateMachine.getHandler().getLooper()); - Assert.assertNotNull(mMceStateMachine); - int initialExpectedState = BluetoothProfile.STATE_CONNECTING; - assertThat(mMceStateMachine.getState()).isEqualTo(initialExpectedState); - if (Looper.myLooper() == null) { - Looper.prepare(); - } - mHandler = new Handler(); + mLooper = new TestLooper(); + + mInOrder = inOrder(mService); + + MockSmsContentProvider contentProvider = new MockSmsContentProvider(); + MockContentResolver contentResolver = new MockContentResolver(); + contentResolver.addProvider("sms", contentProvider); + contentResolver.addProvider("mms", contentProvider); + contentResolver.addProvider("mms-sms", contentProvider); + + when(mService.getContentResolver()).thenReturn(contentResolver); - when(mMockRequestOwnNumberCompletedWithNumber.isSearchCompleted()).thenReturn(true); - when(mMockRequestOwnNumberCompletedWithNumber.getOwnNumber()) - .thenReturn(TEST_OWN_PHONE_NUMBER); - when(mMockRequestOwnNumberIncompleteSearch.isSearchCompleted()).thenReturn(false); - when(mMockRequestOwnNumberIncompleteSearch.getOwnNumber()).thenReturn(null); + doReturn(mTargetContext.getResources()).when(mService).getResources(); + + when(mMasClient.makeRequest(any(Request.class))).thenReturn(true); + mStateMachine = + new MceStateMachine( + mService, + mDevice, + mAdapterService, + mLooper.getLooper(), + mMasClient, + mDatabase); + mLooper.dispatchAll(); + verifyStateTransitionAndIntent( + STATE_DISCONNECTED, STATE_CONNECTING); + + when(mRequestOwnNumberCompletedWithNumber.isSearchCompleted()).thenReturn(true); + when(mRequestOwnNumberCompletedWithNumber.getOwnNumber()).thenReturn(TEST_OWN_PHONE_NUMBER); + when(mRequestOwnNumberIncompleteSearch.isSearchCompleted()).thenReturn(false); + when(mRequestOwnNumberIncompleteSearch.getOwnNumber()).thenReturn(null); createTestMessages(); - when(mMockRequestGetMessage.getMessage()).thenReturn(mTestIncomingSmsBmessage); - when(mMockRequestGetMessage.getHandle()).thenReturn(mTestMessageSmsHandle); + when(mRequestGetMessage.getMessage()).thenReturn(mTestIncomingSmsBmessage); + when(mRequestGetMessage.getHandle()).thenReturn(mTestMessageSmsHandle); - when(mMockMapClientService.getSystemService(Context.TELEPHONY_SERVICE)) - .thenReturn(mMockTelephonyManager); - when(mMockTelephonyManager.isSmsCapable()).thenReturn(false); + when(mService.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mTelephonyManager.isSmsCapable()).thenReturn(false); // Set up receiver for 'Sent' and 'Delivered' PendingIntents IntentFilter filter = new IntentFilter(); @@ -270,21 +247,17 @@ public class MapClientStateMachineTest { @After public void tearDown() throws Exception { - if (mMceStateMachine != null) { - mMceStateMachine.doQuit(); + if (mStateMachine != null) { + mStateMachine.doQuit(); } - if (mIsAdapterServiceSet) { - TestUtils.clearAdapterService(mAdapterService); - } mTargetContext.unregisterReceiver(mSentDeliveryReceiver); } /** Test that default state is STATE_CONNECTING */ @Test public void testDefaultConnectingState() { - Log.i(TAG, "in testDefaultConnectingState"); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mMceStateMachine.getState()); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING); } /** @@ -293,197 +266,114 @@ public class MapClientStateMachineTest { */ @Test public void testStateTransitionFromConnectingToDisconnected() { - Log.i(TAG, "in testStateTransitionFromConnectingToDisconnected"); setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_DISCONNECTED); - mMceStateMachine.sendMessage(msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_DISCONNECTED); - // Wait until the message is processed and a broadcast request is sent to - // to MapClientService to change - // state from STATE_CONNECTING to STATE_DISCONNECTED - verify(mMockMapClientService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) - .sendBroadcastMultiplePermissions( - mIntentArgument.capture(), - any(String[].class), - any(BroadcastOptions.class)); - assertThat(mMceStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + verifyStateTransitionAndIntent(STATE_CONNECTING, STATE_DISCONNECTED); } - /** Test transition from STATE_CONNECTING --> (receive MSG_MAS_CONNECTED) --> STATE_CONNECTED */ @Test - public void testStateTransitionFromConnectingToConnected() { - Log.i(TAG, "in testStateTransitionFromConnectingToConnected"); + public void masConnected_whenConnecting_isConnected() { setupSdpRecordReceipt(); - - int expectedFromState = BluetoothProfile.STATE_CONNECTING; - int expectedToState = BluetoothProfile.STATE_CONNECTED; - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - initiateAndVerifyStateTransitionAndIntent(expectedFromState, expectedToState, msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_CONNECTED); + verifyStateTransitionAndIntent(STATE_CONNECTING, STATE_CONNECTED); } - /** - * Test transition from STATE_CONNECTING --> (receive MSG_MAS_CONNECTED) --> STATE_CONNECTED --> - * (receive MSG_MAS_DISCONNECTED) --> STATE_DISCONNECTING --> STATE_DISCONNECTED - */ @Test - public void testStateTransitionFromConnectedToDisconnected() { - Log.i(TAG, "in testStateTransitionFromConnectedWithMasDisconnected"); + public void masDisconnected_whenConnected_isDisconnected() { + masConnected_whenConnecting_isConnected(); // transition to the connected state - setupSdpRecordReceipt(); - // transition to the connected state - testStateTransitionFromConnectingToConnected(); - - int expectedFromState = BluetoothProfile.STATE_DISCONNECTING; - int expectedToState = BluetoothProfile.STATE_DISCONNECTED; - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_DISCONNECTED); - initiateAndVerifyStateTransitionAndIntent(expectedFromState, expectedToState, msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_DISCONNECTED); + verifyStateTransitionAndIntent(STATE_DISCONNECTING, STATE_DISCONNECTED); } /** Test receiving an empty event report */ @Test public void testReceiveEmptyEvent() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // Wait until the message is processed and a broadcast request is sent to - // to MapClientService to change - // state from STATE_CONNECTING to STATE_CONNECTED - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); - - // Send an empty notification event, verify the mMceStateMachine is still connected - Message notification = Message.obtain(mHandler, MceStateMachine.MSG_NOTIFICATION); - mMceStateMachine.getCurrentState().processMessage(notification); - assertThat(mMceStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state + + // Send an empty notification event, verify the mStateMachine is still connected + sendAndDispatchMessage(MceStateMachine.MSG_NOTIFICATION); + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); } /** Test set message status */ @Test public void testSetMessageStatus() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // Wait until the message is processed and a broadcast request is sent to - // to MapClientService to change - // state from STATE_CONNECTING to STATE_CONNECTED - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); - assertThat(mMceStateMachine.setMessageStatus("123456789AB", BluetoothMapClient.READ)) - .isTrue(); + masConnected_whenConnecting_isConnected(); // transition to the connected state + + // broadcast request is sent to change state from STATE_CONNECTING to STATE_CONNECTED + assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED); + assertThat(mStateMachine.setMessageStatus("123456789AB", BluetoothMapClient.READ)).isTrue(); } /** Test MceStateMachine#disconnect */ @Test public void testDisconnect() { - setupSdpRecordReceipt(); - doAnswer( - invocation -> { - mMceStateMachine.sendMessage(MceStateMachine.MSG_MAS_DISCONNECTED); - return null; - }) - .when(mMockMasClient) - .shutdown(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // Wait until the message is processed and a broadcast request is sent to - // to MapClientService to change - // state from STATE_CONNECTING to STATE_CONNECTED - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); - - mMceStateMachine.disconnect(); - - verify(mMockMapClientService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(4)) - .sendBroadcastMultiplePermissions( - mIntentArgument.capture(), - any(String[].class), - any(BroadcastOptions.class)); + masConnected_whenConnecting_isConnected(); // transition to the connected state - assertThat(mMceStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + mStateMachine.disconnect(); + mLooper.dispatchAll(); + verifyStateTransitionAndIntent(STATE_CONNECTED, STATE_DISCONNECTING); + + verify(mMasClient).shutdown(); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_DISCONNECTED); + verifyStateTransitionAndIntent( + STATE_DISCONNECTING, STATE_DISCONNECTED); } /** Test disconnect timeout */ @Test public void testDisconnectTimeout() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); + masConnected_whenConnecting_isConnected(); // transition to the connected state - // Wait until the message is processed and a broadcast request is sent to - // to MapClientService to change - // state from STATE_CONNECTING to STATE_CONNECTED - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + mStateMachine.disconnect(); + mLooper.dispatchAll(); + verifyStateTransitionAndIntent(STATE_CONNECTED, STATE_DISCONNECTING); - mMceStateMachine.disconnect(); - verify(mMockMapClientService, after(DISCONNECT_TIMEOUT / 2).times(3)) - .sendBroadcastMultiplePermissions( - mIntentArgument.capture(), - any(String[].class), - any(BroadcastOptions.class)); - assertThat(mMceStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTING); - - verify(mMockMapClientService, timeout(DISCONNECT_TIMEOUT).times(4)) - .sendBroadcastMultiplePermissions( - mIntentArgument.capture(), - any(String[].class), - any(BroadcastOptions.class)); - assertThat(mMceStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + mLooper.moveTimeForward(MceStateMachine.DISCONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); + verifyStateTransitionAndIntent(STATE_DISCONNECTING, STATE_DISCONNECTED); } /** Test sending a message to a phone */ @Test public void testSendSMSMessageToPhone() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state String testMessage = "Hello World!"; Uri[] contacts = new Uri[] {Uri.parse("tel://5551212")}; - verify(mMockMasClient, times(0)).makeRequest(any(RequestPushMessage.class)); - mMceStateMachine.sendMapMessage(contacts, testMessage, null, null); - verify(mMockMasClient, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) - .makeRequest(any(RequestPushMessage.class)); + verify(mMasClient, never()).makeRequest(any(RequestPushMessage.class)); + mStateMachine.sendMapMessage(contacts, testMessage, null, null); + mLooper.dispatchAll(); + verify(mMasClient).makeRequest(any(RequestPushMessage.class)); } /** Test sending a message to an email */ @Test public void testSendSMSMessageToEmail() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state String testMessage = "Hello World!"; Uri[] contacts = new Uri[] {Uri.parse("mailto://sms-test@google.com")}; - verify(mMockMasClient, times(0)).makeRequest(any(RequestPushMessage.class)); - mMceStateMachine.sendMapMessage(contacts, testMessage, null, null); - verify(mMockMasClient, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) - .makeRequest(any(RequestPushMessage.class)); + verify(mMasClient, never()).makeRequest(any(RequestPushMessage.class)); + mStateMachine.sendMapMessage(contacts, testMessage, null, null); + mLooper.dispatchAll(); + verify(mMasClient).makeRequest(any(RequestPushMessage.class)); } /** Test message sent successfully */ @Test public void testSMSMessageSent() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); - - when(mMockRequestPushMessage.getMsgHandle()).thenReturn(mTestMessageSmsHandle); - when(mMockRequestPushMessage.getBMsg()).thenReturn(mTestIncomingSmsBmessage); - Message msgSent = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestPushMessage); - - mMceStateMachine.sendMessage(msgSent); - - TestUtils.waitForLooperToFinishScheduledTask(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase) + masConnected_whenConnecting_isConnected(); // transition to the connected state + + when(mRequestPushMessage.getMsgHandle()).thenReturn(mTestMessageSmsHandle); + when(mRequestPushMessage.getBMsg()).thenReturn(mTestIncomingSmsBmessage); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestPushMessage); + + verify(mDatabase) .storeMessage( eq(mTestIncomingSmsBmessage), eq(mTestMessageSmsHandle), @@ -498,12 +388,11 @@ public class MapClientStateMachineTest { * MessageListing of INBOX folder not sent */ private void testGetOwnNumber_setup() { - testStateTransitionFromConnectingToConnected(); - verify(mMockMasClient, after(ASYNC_CALL_TIMEOUT_MILLIS).never()) - .makeRequest(any(RequestSetNotificationRegistration.class)); - verify(mMockMasClient, never()).makeRequest(any(RequestGetMessagesListing.class)); + masConnected_whenConnecting_isConnected(); + verify(mMasClient, never()).makeRequest(any(RequestSetNotificationRegistration.class)); + verify(mMasClient, never()).makeRequest(any(RequestGetMessagesListing.class)); assertThat( - mMceStateMachine + mStateMachine .getHandler() .hasMessages(MceStateMachine.MSG_SEARCH_OWN_NUMBER_TIMEOUT)) .isTrue(); @@ -517,11 +406,11 @@ public class MapClientStateMachineTest { */ private void testGetOwnNumber_assertNextStageStarted(boolean hasStarted) { if (hasStarted) { - verify(mMockMasClient).makeRequest(any(RequestSetNotificationRegistration.class)); - verify(mMockMasClient, times(2)).makeRequest(any(RequestGetMessagesListing.class)); + verify(mMasClient).makeRequest(any(RequestSetNotificationRegistration.class)); + verify(mMasClient, times(2)).makeRequest(any(RequestGetMessagesListing.class)); ArgumentCaptor<Request> requestCaptor = ArgumentCaptor.forClass(Request.class); - verify(mMockMasClient, atLeastOnce()).makeRequest(requestCaptor.capture()); + verify(mMasClient, atLeastOnce()).makeRequest(requestCaptor.capture()); // There will be multiple calls to {@link MasClient#makeRequest} with different // {@link Request} subtypes; not all of them will be {@link // RequestGetMessagesListing}. @@ -533,9 +422,8 @@ public class MapClientStateMachineTest { .comparingElementsUsing(GET_FOLDER_NAME) .contains(MceStateMachine.FOLDER_SENT); } else { - verify(mMockMasClient, never()) - .makeRequest(any(RequestSetNotificationRegistration.class)); - verify(mMockMasClient, never()).makeRequest(any(RequestGetMessagesListing.class)); + verify(mMasClient, never()).makeRequest(any(RequestSetNotificationRegistration.class)); + verify(mMasClient, never()).makeRequest(any(RequestGetMessagesListing.class)); } } @@ -554,17 +442,12 @@ public class MapClientStateMachineTest { public void testGetOwnNumberCompleted() { testGetOwnNumber_setup(); - Message requestCompletedMsg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestOwnNumberCompletedWithNumber); - mMceStateMachine.sendMessage(requestCompletedMsg); + sendAndDispatchMessage( + MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestOwnNumberCompletedWithNumber); - verify(mMockMasClient, after(ASYNC_CALL_TIMEOUT_MILLIS).never()) - .makeRequest(eq(mMockRequestOwnNumberCompletedWithNumber)); + verify(mMasClient, never()).makeRequest(eq(mRequestOwnNumberCompletedWithNumber)); assertThat( - mMceStateMachine + mStateMachine .getHandler() .hasMessages(MceStateMachine.MSG_SEARCH_OWN_NUMBER_TIMEOUT)) .isFalse(); @@ -587,17 +470,12 @@ public class MapClientStateMachineTest { public void testGetOwnNumberTimedOut() { testGetOwnNumber_setup(); - Message timeoutMsg = - Message.obtain( - mHandler, - MceStateMachine.MSG_SEARCH_OWN_NUMBER_TIMEOUT, - mMockRequestOwnNumberIncompleteSearch); - mMceStateMachine.sendMessage(timeoutMsg); + sendAndDispatchMessage( + MceStateMachine.MSG_SEARCH_OWN_NUMBER_TIMEOUT, mRequestOwnNumberIncompleteSearch); - verify(mMockMasClient, after(ASYNC_CALL_TIMEOUT_MILLIS)) - .abortRequest(mMockRequestOwnNumberIncompleteSearch); + verify(mMasClient).abortRequest(mRequestOwnNumberIncompleteSearch); assertThat( - mMceStateMachine + mStateMachine .getHandler() .hasMessages(MceStateMachine.MSG_MAS_REQUEST_COMPLETED)) .isFalse(); @@ -620,17 +498,12 @@ public class MapClientStateMachineTest { public void testGetOwnNumberIncomplete() { testGetOwnNumber_setup(); - Message requestIncompleteMsg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestOwnNumberIncompleteSearch); - mMceStateMachine.sendMessage(requestIncompleteMsg); + sendAndDispatchMessage( + MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestOwnNumberIncompleteSearch); - verify(mMockMasClient, after(ASYNC_CALL_TIMEOUT_MILLIS)) - .makeRequest(eq(mMockRequestOwnNumberIncompleteSearch)); + verify(mMasClient).makeRequest(eq(mRequestOwnNumberIncompleteSearch)); assertThat( - mMceStateMachine + mStateMachine .getHandler() .hasMessages(MceStateMachine.MSG_SEARCH_OWN_NUMBER_TIMEOUT)) .isTrue(); @@ -640,12 +513,7 @@ public class MapClientStateMachineTest { /** Test seen status set for new SMS */ @Test public void testReceivedNewSms_messageStoredAsUnseen() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // verifying that state machine is in the Connected state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state String dateTime = new ObexTime(Instant.now()).toString(); EventReport event = @@ -657,20 +525,13 @@ public class MapClientStateMachineTest { null, "SMS_GSM"); - mMceStateMachine.receiveEvent(event); + sendAndDispatchEvent(event); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessage); - mMceStateMachine.sendMessage(msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessage); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase) + verify(mDatabase) .storeMessage( eq(mTestIncomingSmsBmessage), eq(mTestMessageSmsHandle), @@ -681,12 +542,7 @@ public class MapClientStateMachineTest { /** Test seen status set for new MMS */ @Test public void testReceivedNewMms_messageStoredAsUnseen() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // verifying that state machine is in the Connected state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state String dateTime = new ObexTime(Instant.now()).toString(); EventReport event = @@ -698,23 +554,16 @@ public class MapClientStateMachineTest { null, "MMS"); - when(mMockRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage); - when(mMockRequestGetMessage.getHandle()).thenReturn(mTestMessageMmsHandle); + when(mRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage); + when(mRequestGetMessage.getHandle()).thenReturn(mTestMessageMmsHandle); - mMceStateMachine.receiveEvent(event); + sendAndDispatchEvent(event); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessage); - mMceStateMachine.sendMessage(msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessage); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase) + verify(mDatabase) .storeMessage( eq(mTestIncomingMmsBmessage), eq(mTestMessageMmsHandle), @@ -724,12 +573,7 @@ public class MapClientStateMachineTest { @Test public void testReceiveNewMessage_handleNotRecognized_messageDropped() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // verifying that state machine is in the Connected state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state // Send new message event with handle A String dateTime = new ObexTime(Instant.now()).toString(); @@ -743,130 +587,79 @@ public class MapClientStateMachineTest { "MMS"); // Prepare to send back message content, but use handle B - when(mMockRequestGetMessage.getHandle()).thenReturn(mTestMessageUnknownHandle); - when(mMockRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage); + when(mRequestGetMessage.getHandle()).thenReturn(mTestMessageUnknownHandle); + when(mRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage); - mMceStateMachine.receiveEvent(event); + sendAndDispatchEvent(event); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessage); - mMceStateMachine.sendMessage(msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessage); // We should drop the message and not store it, as it's not one we requested - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase, never()) + verify(mDatabase, never()) .storeMessage(any(Bmessage.class), anyString(), anyLong(), anyBoolean()); } /** Test seen status set in database on initial download */ @Test public void testDownloadExistingSms_messageStoredAsSeen() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state com.android.bluetooth.mapclient.Message testMessageListingSms = createNewMessage("SMS_GSM", mTestMessageSmsHandle); ArrayList<com.android.bluetooth.mapclient.Message> messageListSms = new ArrayList<>(); messageListSms.add(testMessageListingSms); - when(mMockRequestGetMessagesListing.getList()).thenReturn(messageListSms); - - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_GET_MESSAGE_LISTING, - MceStateMachine.FOLDER_INBOX); - mMceStateMachine.sendMessage(msg); - - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessagesListing.class)); - - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessagesListing); - mMceStateMachine.sendMessage(msg); - - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); - - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessage); - mMceStateMachine.sendMessage(msg); - - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); + when(mRequestGetMessagesListing.getList()).thenReturn(messageListSms); + + sendAndDispatchMessage( + MceStateMachine.MSG_GET_MESSAGE_LISTING, MceStateMachine.FOLDER_INBOX); + + verify(mMasClient).makeRequest(any(RequestGetMessagesListing.class)); + + sendAndDispatchMessage( + MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessagesListing); + + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); + + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessage); + + verify(mDatabase).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); } /** Test seen status set in database on initial download */ @Test public void testDownloadExistingMms_messageStoredAsSeen() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state com.android.bluetooth.mapclient.Message testMessageListingMms = createNewMessage("MMS", mTestMessageMmsHandle); ArrayList<com.android.bluetooth.mapclient.Message> messageListMms = new ArrayList<>(); messageListMms.add(testMessageListingMms); - when(mMockRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage); - when(mMockRequestGetMessage.getHandle()).thenReturn(mTestMessageMmsHandle); - when(mMockRequestGetMessagesListing.getList()).thenReturn(messageListMms); - - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_GET_MESSAGE_LISTING, - MceStateMachine.FOLDER_INBOX); - mMceStateMachine.sendMessage(msg); - - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessagesListing.class)); - - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessagesListing); - mMceStateMachine.sendMessage(msg); - - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); - - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessage); - mMceStateMachine.sendMessage(msg); - - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockDatabase).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); + when(mRequestGetMessage.getMessage()).thenReturn(mTestIncomingMmsBmessage); + when(mRequestGetMessage.getHandle()).thenReturn(mTestMessageMmsHandle); + when(mRequestGetMessagesListing.getList()).thenReturn(messageListMms); + + sendAndDispatchMessage( + MceStateMachine.MSG_GET_MESSAGE_LISTING, MceStateMachine.FOLDER_INBOX); + + verify(mMasClient).makeRequest(any(RequestGetMessagesListing.class)); + + sendAndDispatchMessage( + MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessagesListing); + + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); + + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessage); + + verify(mDatabase).storeMessage(any(), any(), any(), eq(MESSAGE_SEEN)); } /** Test receiving a new message notification. */ @Test public void testReceiveNewMessageNotification() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state // Receive a new message notification. String dateTime = new ObexTime(Instant.now()).toString(); @@ -879,20 +672,15 @@ public class MapClientStateMachineTest { null, "SMS_GSM"); - Message notificationMessage = - Message.obtain(mHandler, MceStateMachine.MSG_NOTIFICATION, (Object) event); - - mMceStateMachine.getCurrentState().processMessage(notificationMessage); + sendAndDispatchEvent(event); - verify(mMockMasClient, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) - .makeRequest(any(RequestGetMessage.class)); + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); MceStateMachine.MessageMetadata messageMetadata = - mMceStateMachine.mMessages.get(mTestMessageSmsHandle); - Assert.assertEquals(messageMetadata.getHandle(), mTestMessageSmsHandle); - Assert.assertEquals( - new ObexTime(Instant.ofEpochMilli(messageMetadata.getTimestamp())).toString(), - dateTime); + mStateMachine.mMessages.get(mTestMessageSmsHandle); + assertThat(messageMetadata.getHandle()).isEqualTo(mTestMessageSmsHandle); + assertThat(new ObexTime(Instant.ofEpochMilli(messageMetadata.getTimestamp())).toString()) + .isEqualTo(dateTime); } /** @@ -901,26 +689,18 @@ public class MapClientStateMachineTest { */ @Test public void testMsgGetMessageListing_unsupportedMessageTypesNotRequested() { - setupSdpRecordReceipt(); - clearInvocations(mMockMasClient); - byte expectedFilter = MessagesFilter.MESSAGE_TYPE_EMAIL | MessagesFilter.MESSAGE_TYPE_IM; - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); + masConnected_whenConnecting_isConnected(); // transition to the connected state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + clearInvocations(mMasClient); + byte expectedFilter = MessagesFilter.MESSAGE_TYPE_EMAIL | MessagesFilter.MESSAGE_TYPE_IM; - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_GET_MESSAGE_LISTING, - MceStateMachine.FOLDER_INBOX); - mMceStateMachine.sendMessage(msg); + sendAndDispatchMessage( + MceStateMachine.MSG_GET_MESSAGE_LISTING, MceStateMachine.FOLDER_INBOX); // using Request class as captor grabs all Request sub-classes even if // RequestGetMessagesListing is specifically requested ArgumentCaptor<Request> requestCaptor = ArgumentCaptor.forClass(Request.class); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient, atLeastOnce()).makeRequest(requestCaptor.capture()); + verify(mMasClient, atLeastOnce()).makeRequest(requestCaptor.capture()); List<Request> requests = requestCaptor.getAllValues(); // iterating through captured values to grab RequestGetMessagesListing object @@ -940,12 +720,7 @@ public class MapClientStateMachineTest { @Test public void testReceivedNewMmsNoSMSDefaultPackage_broadcastToSMSReplyPackage() { - setupSdpRecordReceipt(); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // verifying that state machine is in the Connected state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + masConnected_whenConnecting_isConnected(); // transition to the connected state String dateTime = new ObexTime(Instant.now()).toString(); EventReport event = @@ -957,91 +732,72 @@ public class MapClientStateMachineTest { null, "SMS_GSM"); - mMceStateMachine.receiveEvent(event); + sendAndDispatchEvent(event); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMasClient).makeRequest(any(RequestGetMessage.class)); + verify(mMasClient).makeRequest(any(RequestGetMessage.class)); - msg = - Message.obtain( - mHandler, - MceStateMachine.MSG_MAS_REQUEST_COMPLETED, - mMockRequestGetMessage); - mMceStateMachine.sendMessage(msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, mRequestGetMessage); - TestUtils.waitForLooperToBeIdle(mMceStateMachine.getHandler().getLooper()); - verify(mMockMapClientService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(1)) - .sendBroadcast( - mIntentArgument.capture(), eq(android.Manifest.permission.RECEIVE_SMS)); - assertThat(mIntentArgument.getValue().getPackage()).isNull(); + verifyIntentSent( + android.Manifest.permission.RECEIVE_SMS, hasPackage(nullValue(String.class))); } @Test public void testSdpBusyWhileConnecting_sdpRetried() { - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTING); + assertCurrentStateAfterScheduledTask(STATE_CONNECTING); // Send SDP Failed with status "busy" // Note: There's no way to validate the BluetoothDevice#sdpSearch call - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_BUSY, null); + mStateMachine.sendSdpResult(MceStateMachine.SDP_BUSY, null); // Send successful SDP record, then send MAS Client connected SdpMasRecord record = new SdpMasRecord(1, 1, 1, 1, 1, 1, "MasRecord"); - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, record); - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - mMceStateMachine.sendMessage(msg); - - // Verify we move into the connected state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTED); + mStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, record); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_CONNECTED); + verifyStateTransitionAndIntent(STATE_CONNECTING, STATE_CONNECTED); } @Test public void testSdpBusyWhileConnectingAndRetryResultsReceivedAfterTimeout_resultsIgnored() { - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTING); + assertCurrentStateAfterScheduledTask(STATE_CONNECTING); // Send SDP Failed with status "busy" // Note: There's no way to validate the BluetoothDevice#sdpSearch call - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_BUSY, null); + mStateMachine.sendSdpResult(MceStateMachine.SDP_BUSY, null); - // Timeout waiting for record - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_CONNECTING_TIMEOUT); - mMceStateMachine.sendMessage(msg); + // Simulate timeout waiting for record + mLooper.moveTimeForward(MceStateMachine.CONNECT_TIMEOUT.toMillis()); + mLooper.dispatchAll(); - // Verify we move into the disconnecting state - verify(mMockMapClientService, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(2)) - .sendBroadcastMultiplePermissions( - mIntentArgument.capture(), - any(String[].class), - any(BroadcastOptions.class)); - - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_DISCONNECTING); + verifyStateTransitionAndIntent(STATE_CONNECTING, STATE_DISCONNECTING); // Send successful SDP record, then send MAS Client connected SdpMasRecord record = new SdpMasRecord(1, 1, 1, 1, 1, 1, "MasRecord"); - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, record); + mStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, record); // Verify nothing happens - verifyNoMoreInteractions(mMockMapClientService); + verifyNoMoreInteractions(mService); } @Test public void testSdpFailedWithNoRecordWhileConnecting_deviceDisconnecting() { - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTING); + assertCurrentStateAfterScheduledTask(STATE_CONNECTING); // Send SDP process success with no record found - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, null); + mStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, null); // Verify we move into the disconnecting state - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_DISCONNECTING); + assertCurrentStateAfterScheduledTask(STATE_DISCONNECTING); } @Test public void testSdpOrganicFailure_deviceDisconnecting() { - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTING); + assertCurrentStateAfterScheduledTask(STATE_CONNECTING); // Send SDP Failed entirely - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_FAILED, null); + mStateMachine.sendSdpResult(MceStateMachine.SDP_FAILED, null); - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_DISCONNECTING); + assertCurrentStateAfterScheduledTask(STATE_DISCONNECTING); } /** @@ -1139,10 +895,8 @@ public class MapClientStateMachineTest { * 'Success'/'Failure'. */ private void testSendMapMessagePendingIntents_base(String action, EventReport.Type type) { - int expectedFromState = BluetoothProfile.STATE_CONNECTING; - int expectedToState = BluetoothProfile.STATE_CONNECTED; - Message msg = Message.obtain(mHandler, MceStateMachine.MSG_MAS_CONNECTED); - initiateAndVerifyStateTransitionAndIntent(expectedFromState, expectedToState, msg); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_CONNECTED); + verifyStateTransitionAndIntent(STATE_CONNECTING, STATE_CONNECTED); PendingIntent pendingIntentSent; PendingIntent pendingIntentDelivered; @@ -1159,7 +913,14 @@ public class MapClientStateMachineTest { sendMapMessageWithPendingIntents( pendingIntentSent, pendingIntentDelivered, TEST_MESSAGE_HANDLE); - receiveSentDeliveryEvent(type, TEST_MESSAGE_HANDLE); + sendAndDispatchEvent( + createNewEventReport( + type.toString(), + TEST_DATETIME, + TEST_MESSAGE_HANDLE, + SENT_PATH, + null, + Bmessage.Type.SMS_GSM.toString())); } private PendingIntent createPendingIntent(String action) { @@ -1171,10 +932,10 @@ public class MapClientStateMachineTest { PendingIntent pendingIntentSent, PendingIntent pendingIntentDelivered, String messageHandle) { - mMceStateMachine.sendMapMessage( + mStateMachine.sendMapMessage( TEST_CONTACTS_ONE_PHONENUM, TEST_MESSAGE, pendingIntentSent, pendingIntentDelivered); - TestUtils.waitForLooperToFinishScheduledTask(mMceStateMachine.getHandler().getLooper()); + mLooper.dispatchAll(); // {@link sendMapMessage} leads to a new {@link RequestPushMessage}, which contains // a {@link Bmessage} object that is used as a key to a map to retrieve the corresponding @@ -1187,60 +948,33 @@ public class MapClientStateMachineTest { ArgumentCaptor<RequestPushMessage> requestCaptor = ArgumentCaptor.forClass(RequestPushMessage.class); - verify(mMockMasClient, atLeastOnce()).makeRequest(requestCaptor.capture()); + verify(mMasClient, atLeastOnce()).makeRequest(requestCaptor.capture()); RequestPushMessage spyRequestPushMessage = spy(requestCaptor.getValue()); when(spyRequestPushMessage.getMsgHandle()).thenReturn(messageHandle); - Message msgSent = - Message.obtain( - mHandler, MceStateMachine.MSG_MAS_REQUEST_COMPLETED, spyRequestPushMessage); - - mMceStateMachine.sendMessage(msgSent); - TestUtils.waitForLooperToFinishScheduledTask(mMceStateMachine.getHandler().getLooper()); - } - - private void receiveSentDeliveryEvent(EventReport.Type type, String messageHandle) { - mMceStateMachine.receiveEvent( - createNewEventReport( - type.toString(), - TEST_DATETIME, - messageHandle, - SENT_PATH, - null, - Bmessage.Type.SMS_GSM.toString())); + sendAndDispatchMessage(MceStateMachine.MSG_MAS_REQUEST_COMPLETED, spyRequestPushMessage); } private void setupSdpRecordReceipt() { - assertCurrentStateAfterScheduledTask(BluetoothProfile.STATE_CONNECTING); + assertCurrentStateAfterScheduledTask(STATE_CONNECTING); // Setup receipt of SDP record SdpMasRecord record = new SdpMasRecord(1, 1, 1, 1, 1, 1, "MasRecord"); - mMceStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, record); + mStateMachine.sendSdpResult(MceStateMachine.SDP_SUCCESS, record); } private void assertCurrentStateAfterScheduledTask(int expectedState) { - TestUtils.waitForLooperToFinishScheduledTask(mMceStateMachine.getHandler().getLooper()); - assertThat(mMceStateMachine.getState()).isEqualTo(expectedState); + mLooper.dispatchAll(); + assertThat(mStateMachine.getState()).isEqualTo(expectedState); } - private void initiateAndVerifyStateTransitionAndIntent( - int expectedFromState, int expectedToState, Message msg) { - mMceStateMachine.sendMessage(msg); - assertCurrentStateAfterScheduledTask(expectedToState); - verify(mMockMapClientService, atLeastOnce()) - .sendBroadcastMultiplePermissions( - mIntentArgument.capture(), - any(String[].class), - any(BroadcastOptions.class)); - Intent capturedIntent = mIntentArgument.getValue(); - int intentFromState = - capturedIntent.getIntExtra( - BluetoothProfile.EXTRA_PREVIOUS_STATE, CONNECTION_STATE_UNDEFINED); - int intentToState = - capturedIntent.getIntExtra( - BluetoothProfile.EXTRA_STATE, CONNECTION_STATE_UNDEFINED); - assertThat(intentFromState).isEqualTo(expectedFromState); - assertThat(intentToState).isEqualTo(expectedToState); + private void verifyStateTransitionAndIntent(int oldState, int newState) { + assertThat(mStateMachine.getState()).isEqualTo(newState); + verifyIntentSent( + new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}, + hasAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(EXTRA_STATE, newState), + hasExtra(EXTRA_PREVIOUS_STATE, oldState)); } private static class MockSmsContentProvider extends MockContentProvider { @@ -1328,24 +1062,52 @@ public class MapClientStateMachineTest { // create new Bmessages for testing void createTestMessages() { - mOriginator = new VCardEntry(); + VCardEntry originator = new VCardEntry(); VCardProperty property = new VCardProperty(); property.setName(VCardConstants.PROPERTY_TEL); property.addValues("555-1212"); - mOriginator.addProperty(property); + originator.addProperty(property); mTestIncomingSmsBmessage = new Bmessage(); mTestIncomingSmsBmessage.setBodyContent("HelloWorld"); mTestIncomingSmsBmessage.setType(Bmessage.Type.SMS_GSM); mTestIncomingSmsBmessage.setFolder("telecom/msg/inbox"); - mTestIncomingSmsBmessage.addOriginator(mOriginator); - mTestIncomingSmsBmessage.addRecipient(mOriginator); + mTestIncomingSmsBmessage.addOriginator(originator); + mTestIncomingSmsBmessage.addRecipient(originator); mTestIncomingMmsBmessage = new Bmessage(); mTestIncomingMmsBmessage.setBodyContent("HelloWorld"); mTestIncomingMmsBmessage.setType(Bmessage.Type.MMS); mTestIncomingMmsBmessage.setFolder("telecom/msg/inbox"); - mTestIncomingMmsBmessage.addOriginator(mOriginator); - mTestIncomingMmsBmessage.addRecipient(mOriginator); + mTestIncomingMmsBmessage.addOriginator(originator); + mTestIncomingMmsBmessage.addRecipient(originator); + } + + private void sendAndDispatchEvent(EventReport ev) { + sendAndDispatchMessage(MceStateMachine.MSG_NOTIFICATION, ev); + } + + private void sendAndDispatchMessage(int what) { + sendAndDispatchMessage(what, null); + } + + private void sendAndDispatchMessage(int what, Object obj) { + mStateMachine.sendMessage(what, obj); + mLooper.dispatchAll(); + } + + @SafeVarargs + private void verifyIntentSent(String permission, Matcher<Intent>... matchers) { + mInOrder.verify(mService) + .sendBroadcast(MockitoHamcrest.argThat(AllOf.allOf(matchers)), eq(permission)); + } + + @SafeVarargs + private void verifyIntentSent(String[] permissions, Matcher<Intent>... matchers) { + mInOrder.verify(mService) + .sendBroadcastMultiplePermissions( + MockitoHamcrest.argThat(AllOf.allOf(matchers)), + eq(permissions), + any(BroadcastOptions.class)); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java index 4086981761..93837ebebd 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java @@ -37,7 +37,6 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -123,12 +122,12 @@ public class MapClientTest { // is the statemachine created Map<BluetoothDevice, MceStateMachine> map = mService.getInstanceMap(); - Assert.assertEquals(1, map.size()); + assertThat(map.size()).isEqualTo(1); MceStateMachine sm = map.get(device); assertThat(sm).isNotNull(); TestUtils.waitForLooperToFinishScheduledTask(sm.getHandler().getLooper()); - Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, sm.getState()); + assertThat(sm.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING); mService.cleanupDevice(device, sm); assertThat(mService.getInstanceMap()).doesNotContainKey(device); } @@ -171,7 +170,7 @@ public class MapClientTest { // verify Map<BluetoothDevice, MceStateMachine> map = mService.getInstanceMap(); - Assert.assertEquals(MapClientService.MAXIMUM_CONNECTED_DEVICES, map.size()); + assertThat(map.size()).isEqualTo(MapClientService.MAXIMUM_CONNECTED_DEVICES); for (BluetoothDevice d : list) { assertThat(map).containsKey(d); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java index 85e5e18607..12bcf80f3c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java @@ -39,10 +39,10 @@ public class MessagesFilterTest { assertThat(filter.originator).isEqualTo(originator); filter.setOriginator(""); - assertThat(filter.originator).isEqualTo(null); // Empty string is stored as null + assertThat(filter.originator).isNull(); // Empty string is stored as null filter.setOriginator(null); - assertThat(filter.originator).isEqualTo(null); + assertThat(filter.originator).isNull(); } @Test @@ -74,10 +74,10 @@ public class MessagesFilterTest { assertThat(filter.recipient).isEqualTo(recipient); filter.setRecipient(""); - assertThat(filter.recipient).isEqualTo(null); // Empty string is stored as null + assertThat(filter.recipient).isNull(); // Empty string is stored as null filter.setRecipient(null); - assertThat(filter.recipient).isEqualTo(null); + assertThat(filter.recipient).isNull(); } /** Test Builder creates and sets everything correctly. */ diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/ObexTimeTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/ObexTimeTest.java index 5b472d15a4..6f8bad385c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/ObexTimeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/ObexTimeTest.java @@ -16,11 +16,12 @@ package com.android.bluetooth.mapclient; +import static com.google.common.truth.Truth.assertThat; + import android.annotation.SuppressLint; import androidx.test.runner.AndroidJUnit4; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -78,94 +79,60 @@ public class ObexTimeTest { @Test public void createWithValidDateTimeString_TimestampCorrect() { ObexTime timestamp = new ObexTime(VALID_TIME_STRING); - Assert.assertEquals( - "Parsed instant must match expected", - VALID_INSTANT_LOCAL_TZ, - timestamp.getInstant()); - Assert.assertEquals( - "Parsed date must match expected", VALID_DATE_LOCAL_TZ, timestamp.getTime()); + assertThat(timestamp.getInstant()).isEqualTo(VALID_INSTANT_LOCAL_TZ); + assertThat(timestamp.getTime()).isEqualTo(VALID_DATE_LOCAL_TZ); } @Test public void createWithValidDateTimeStringWithPosOffset_TimestampCorrect() { ObexTime timestamp = new ObexTime(VALID_TIME_STRING_WITH_OFFSET_POS); - Assert.assertEquals( - "Parsed instant must match expected", - VALID_INSTANT_WITH_OFFSET_POS, - timestamp.getInstant()); - Assert.assertEquals( - "Parsed date must match expected", VALID_DATE_WITH_OFFSET_POS, timestamp.getTime()); + assertThat(timestamp.getInstant()).isEqualTo(VALID_INSTANT_WITH_OFFSET_POS); + assertThat(timestamp.getTime()).isEqualTo(VALID_DATE_WITH_OFFSET_POS); } @Test public void createWithValidDateTimeStringWithNegOffset_TimestampCorrect() { ObexTime timestamp = new ObexTime(VALID_TIME_STRING_WITH_OFFSET_NEG); - Assert.assertEquals( - "Parsed instant must match expected", - VALID_INSTANT_WITH_OFFSET_NEG, - timestamp.getInstant()); - Assert.assertEquals( - "Parsed date must match expected", VALID_DATE_WITH_OFFSET_NEG, timestamp.getTime()); + assertThat(timestamp.getInstant()).isEqualTo(VALID_INSTANT_WITH_OFFSET_NEG); + assertThat(timestamp.getTime()).isEqualTo(VALID_DATE_WITH_OFFSET_NEG); } @Test public void createWithValidDate_TimestampCorrect() { ObexTime timestamp = new ObexTime(VALID_DATE_LOCAL_TZ); - Assert.assertEquals( - "ObexTime created with a date must return the expected instant", - VALID_INSTANT_LOCAL_TZ, - timestamp.getInstant()); - Assert.assertEquals( - "ObexTime created with a date must return the same date", - VALID_DATE_LOCAL_TZ, - timestamp.getTime()); + assertThat(timestamp.getInstant()).isEqualTo(VALID_INSTANT_LOCAL_TZ); + assertThat(timestamp.getTime()).isEqualTo(VALID_DATE_LOCAL_TZ); } @SuppressWarnings("JavaUtilDate") @Test public void createWithValidInstant_TimestampCorrect() { ObexTime timestamp = new ObexTime(VALID_INSTANT); - Assert.assertEquals( - "ObexTime created with a instant must return the same instant", - VALID_INSTANT, - timestamp.getInstant()); - Assert.assertEquals( - "ObexTime created with a instant must return the expected date", - VALID_DATE, - timestamp.getTime()); + assertThat(timestamp.getInstant()).isEqualTo(VALID_INSTANT); + assertThat(timestamp.getTime()).isEqualTo(VALID_DATE); } @Test public void printValidTime_TimestampMatchesInput() { ObexTime timestamp = new ObexTime(VALID_TIME_STRING); - Assert.assertEquals( - "Timestamp as a string must match the input string", - VALID_TIME_STRING, - timestamp.toString()); + assertThat(timestamp.toString()).isEqualTo(VALID_TIME_STRING); } @Test public void createWithInvalidDelimiterString_TimestampIsNull() { ObexTime timestamp = new ObexTime(INVALID_TIME_STRING_BAD_DELIMITER); - Assert.assertEquals( - "Parsed timestamp was invalid and must result in a null object", - null, - timestamp.getTime()); + assertThat(timestamp.getTime()).isNull(); } @Test public void createWithInvalidOffsetString_TimestampIsNull() { ObexTime timestamp = new ObexTime(INVALID_TIME_STRING_OFFSET_EXTRA_DIGITS); - Assert.assertEquals( - "Parsed timestamp was invalid and must result in a null object", - null, - timestamp.getTime()); + assertThat(timestamp.getTime()).isNull(); } @Test public void printInvalidTime_ReturnsNull() { ObexTime timestamp = new ObexTime(INVALID_TIME_STRING_BAD_DELIMITER); - Assert.assertEquals( - "Invalid timestamps must return null for toString()", null, timestamp.toString()); + assertThat(timestamp.toString()).isNull(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestTest.java index 16cc355cdd..2320b71b1c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestTest.java @@ -134,7 +134,7 @@ public class RequestTest { false, /*retry*/ false); assertThat(newRequest).isNotNull(); - assertThat(newRequest.getMsgHandle()).isEqualTo(null); + assertThat(newRequest.getMsgHandle()).isNull(); newRequest.execute(mFakeClientSession); assertThat(newRequest.isSuccess()).isTrue(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java index dd9e61ae7f..7f519f2f01 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java @@ -100,13 +100,13 @@ public class McpServiceTest { mMcpService.setDeviceAuthorized(device0, true); verify(mMediaControlProfile).onDeviceAuthorizationSet(eq(device0)); - Assert.assertEquals( - BluetoothDevice.ACCESS_ALLOWED, mMcpService.getDeviceAuthorization(device0)); + assertThat(mMcpService.getDeviceAuthorization(device0)) + .isEqualTo(BluetoothDevice.ACCESS_ALLOWED); mMcpService.setDeviceAuthorized(device1, false); verify(mMediaControlProfile).onDeviceAuthorizationSet(eq(device1)); - Assert.assertEquals( - BluetoothDevice.ACCESS_REJECTED, mMcpService.getDeviceAuthorization(device1)); + assertThat(mMcpService.getDeviceAuthorization(device1)) + .isEqualTo(BluetoothDevice.ACCESS_REJECTED); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java index 3da40b9bbd..1e9b210a77 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java @@ -39,7 +39,6 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -135,8 +134,8 @@ public class MediaControlGattServiceTest { doReturn(mMandatoryFeatures).when(mMockMcsCallbacks).onGetFeatureFlags(); assertThat(mMcpService.init(UUID_GMCS)).isTrue(); - Assert.assertEquals(mMcpService.getServiceUuid(), UUID_GMCS); - Assert.assertEquals(mMcpService.getContentControlId(), TEST_CCID); + assertThat(mMcpService.getServiceUuid()).isEqualTo(UUID_GMCS); + assertThat(mMcpService.getContentControlId()).isEqualTo(TEST_CCID); doReturn(true).when(mMockGattServer).removeService(any(BluetoothGattService.class)); mMcpService.destroy(); @@ -210,216 +209,226 @@ public class MediaControlGattServiceTest { BluetoothGattCharacteristic characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_NAME); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals("", characteristic.getStringValue(0)); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getStringValue(0)).isEmpty(); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_TITLE); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals("", characteristic.getStringValue(0)); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getStringValue(0)).isEmpty(); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_DURATION); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - 0xFFFFFFFF, - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) - .intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) + .intValue()) + .isEqualTo(0xFFFFFFFF); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - 0xFFFFFFFF, - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) - .intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) + .intValue()) + .isEqualTo(0xFFFFFFFF); characteristic = service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - MediaState.INACTIVE.getValue(), - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + .intValue()) + .isEqualTo(MediaState.INACTIVE.getValue()); characteristic = service.getCharacteristic(MediaControlGattService.UUID_CONTENT_CONTROL_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); - Assert.assertEquals( - TEST_CCID, - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo(BluetoothGattCharacteristic.PROPERTY_READ); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + .intValue()) + .isEqualTo(TEST_CCID); // Check initial state of all optional characteristics characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); + assertThat(characteristic.getProperties()) + .isEqualTo(BluetoothGattCharacteristic.PROPERTY_READ); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_URL); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); - Assert.assertEquals("", characteristic.getStringValue(0)); + assertThat(characteristic.getProperties()) + .isEqualTo(BluetoothGattCharacteristic.PROPERTY_READ); + assertThat(characteristic.getStringValue(0)).isEmpty(); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_CHANGED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getProperties()) + .isEqualTo(BluetoothGattCharacteristic.PROPERTY_NOTIFY); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - 0, - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 0).intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 0) + .intValue()) + .isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEEKING_SPEED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - 0, - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 0).intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT8, 0) + .intValue()) + .isEqualTo(0); characteristic = service.getCharacteristic( MediaControlGattService.UUID_CURRENT_TRACK_SEGMENT_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); + assertThat(characteristic.getProperties()) + .isEqualTo(BluetoothGattCharacteristic.PROPERTY_READ); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_CURRENT_TRACK_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_NEXT_TRACK_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_CURRENT_GROUP_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PARENT_GROUP_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - PlayingOrder.SINGLE_ONCE.getValue(), - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + .intValue()) + .isEqualTo(PlayingOrder.SINGLE_ONCE.getValue()); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER_SUPPORTED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), BluetoothGattCharacteristic.PROPERTY_READ); - Assert.assertEquals( - SupportedPlayingOrder.SINGLE_ONCE, - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0) - .intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo(BluetoothGattCharacteristic.PROPERTY_READ); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0) + .intValue()) + .isEqualTo(SupportedPlayingOrder.SINGLE_ONCE); characteristic = service.getCharacteristic(MediaControlGattService.UUID_MEDIA_CONTROL_POINT); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_NOTIFY - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_NOTIFY + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE); characteristic = service.getCharacteristic( MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); - Assert.assertEquals( - MediaControlGattService.INITIAL_SUPPORTED_OPCODES, - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) - .intValue()); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) + .intValue()) + .isEqualTo(MediaControlGattService.INITIAL_SUPPORTED_OPCODES); characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEARCH_RESULT_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_READ - | BluetoothGattCharacteristic.PROPERTY_NOTIFY); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_READ + | BluetoothGattCharacteristic.PROPERTY_NOTIFY); assertThat(characteristic.getValue().length).isEqualTo(0); characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEARCH_CONTROL_POINT); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - characteristic.getProperties(), - BluetoothGattCharacteristic.PROPERTY_NOTIFY - | BluetoothGattCharacteristic.PROPERTY_WRITE - | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE); + assertThat(characteristic.getProperties()) + .isEqualTo( + BluetoothGattCharacteristic.PROPERTY_NOTIFY + | BluetoothGattCharacteristic.PROPERTY_WRITE + | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE); } @Test @@ -488,78 +497,81 @@ public class MediaControlGattServiceTest { BluetoothGattCharacteristic characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYBACK_SPEED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - playback_speed, mMcpService.getPlaybackSpeedChar().floatValue(), 0.001f); + assertThat(mMcpService.getPlaybackSpeedChar().floatValue()).isEqualTo(playback_speed); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - playing_order.getValue(), - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + .intValue()) + .isEqualTo(playing_order.getValue()); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_POSITION); assertThat(characteristic).isNotNull(); // Set value as ms, kept in characteristic as 0.01s - Assert.assertEquals( - track_position / 10, - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) - .intValue()); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) + .intValue()) + .isEqualTo(track_position / 10); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_NAME); assertThat(characteristic).isNotNull(); - Assert.assertEquals(player_name, characteristic.getStringValue(0)); + assertThat(characteristic.getStringValue(0)).isEqualTo(player_name); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_URL); assertThat(characteristic).isNotNull(); - Assert.assertEquals(icon_url, characteristic.getStringValue(0)); + assertThat(characteristic.getStringValue(0)).isEqualTo(icon_url); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYER_ICON_OBJ_ID); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - icon_obj_id.longValue(), mMcpService.byteArray2ObjId(characteristic.getValue())); + assertThat(mMcpService.byteArray2ObjId(characteristic.getValue())) + .isEqualTo(icon_obj_id.longValue()); characteristic = service.getCharacteristic(MediaControlGattService.UUID_PLAYING_ORDER_SUPPORTED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - playing_order_supported.intValue(), - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0) - .intValue()); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, 0) + .intValue()) + .isEqualTo(playing_order_supported.intValue()); characteristic = service.getCharacteristic( MediaControlGattService.UUID_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - opcodes_supported.intValue(), - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) - .intValue()); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, 0) + .intValue()) + .isEqualTo(opcodes_supported.intValue()); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_TITLE); assertThat(characteristic).isNotNull(); - Assert.assertEquals(track_title, characteristic.getStringValue(0)); + assertThat(characteristic.getStringValue(0)).isEqualTo(track_title); characteristic = service.getCharacteristic(MediaControlGattService.UUID_TRACK_DURATION); assertThat(characteristic).isNotNull(); // Set value as ms, kept in characteristic as 0.01s - Assert.assertEquals( - track_duration / 10, - characteristic - .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) - .intValue()); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_SINT32, 0) + .intValue()) + .isEqualTo(track_duration / 10); characteristic = service.getCharacteristic(MediaControlGattService.UUID_MEDIA_STATE); assertThat(characteristic).isNotNull(); - Assert.assertEquals( - playback_state.getValue(), - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0).intValue()); + assertThat( + characteristic + .getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0) + .intValue()) + .isEqualTo(playback_state.getValue()); characteristic = service.getCharacteristic(MediaControlGattService.UUID_SEEKING_SPEED); assertThat(characteristic).isNotNull(); - Assert.assertEquals(seeking_speed, mMcpService.getSeekingSpeedChar().floatValue(), 0.001f); + assertThat(mMcpService.getSeekingSpeedChar().floatValue()).isEqualTo(seeking_speed); } private void verifyWriteObjIdsValid( @@ -931,9 +943,8 @@ public class MediaControlGattServiceTest { bb.putInt(value); } - Assert.assertEquals( - expectedGattResult, - mMcpService.handleMediaControlPointRequest(mCurrentDevice, bb.array())); + assertThat(mMcpService.handleMediaControlPointRequest(mCurrentDevice, bb.array())) + .isEqualTo(expectedGattResult); if (expectedGattResult == BluetoothGatt.GATT_SUCCESS) { // Verify if callback comes to profile diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java index 1da98c68af..8c134f1980 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java @@ -156,57 +156,46 @@ public class MediaControlProfileTest { // Some duration mMockMetadata.duration = Long.toString(duration); - Assert.assertEquals(duration, mMediaControlProfile.getCurrentTrackDuration()); + assertThat(mMediaControlProfile.getCurrentTrackDuration()).isEqualTo(duration); // No metadata equals no track duration mMockMediaData.metadata = null; - Assert.assertEquals( - MediaControlGattServiceInterface.TRACK_DURATION_UNAVAILABLE, - mMediaControlProfile.getCurrentTrackDuration()); + assertThat(mMediaControlProfile.getCurrentTrackDuration()) + .isEqualTo(MediaControlGattServiceInterface.TRACK_DURATION_UNAVAILABLE); } @Test public void testPlayerState2McsState() { - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PLAYING), - MediaState.PLAYING); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_NONE), - MediaState.INACTIVE); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_STOPPED), - MediaState.PAUSED); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PAUSED), - MediaState.PAUSED); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PLAYING), - MediaState.PLAYING); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_FAST_FORWARDING), - MediaState.SEEKING); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_REWINDING), - MediaState.SEEKING); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_BUFFERING), - MediaState.PAUSED); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_ERROR), - MediaState.INACTIVE); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_CONNECTING), - MediaState.INACTIVE); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_SKIPPING_TO_PREVIOUS), - MediaState.PAUSED); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState(PlaybackState.STATE_SKIPPING_TO_NEXT), - MediaState.PAUSED); - Assert.assertEquals( - mMediaControlProfile.playerState2McsState( - PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM), - MediaState.PAUSED); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PLAYING)) + .isEqualTo(MediaState.PLAYING); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_NONE)) + .isEqualTo(MediaState.INACTIVE); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_STOPPED)) + .isEqualTo(MediaState.PAUSED); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PAUSED)) + .isEqualTo(MediaState.PAUSED); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_PLAYING)) + .isEqualTo(MediaState.PLAYING); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_FAST_FORWARDING)) + .isEqualTo(MediaState.SEEKING); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_REWINDING)) + .isEqualTo(MediaState.SEEKING); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_BUFFERING)) + .isEqualTo(MediaState.PAUSED); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_ERROR)) + .isEqualTo(MediaState.INACTIVE); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_CONNECTING)) + .isEqualTo(MediaState.INACTIVE); + assertThat( + mMediaControlProfile.playerState2McsState( + PlaybackState.STATE_SKIPPING_TO_PREVIOUS)) + .isEqualTo(MediaState.PAUSED); + assertThat(mMediaControlProfile.playerState2McsState(PlaybackState.STATE_SKIPPING_TO_NEXT)) + .isEqualTo(MediaState.PAUSED); + assertThat( + mMediaControlProfile.playerState2McsState( + PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM)) + .isEqualTo(MediaState.PAUSED); } @Test @@ -215,9 +204,8 @@ public class MediaControlProfileTest { long position = 10; float playback_speed = 1.5f; - Assert.assertEquals( - mMcpServiceCallbacks.onGetCurrentTrackPosition(), - MediaControlGattServiceInterface.TRACK_POSITION_UNAVAILABLE); + assertThat(mMcpServiceCallbacks.onGetCurrentTrackPosition()) + .isEqualTo(MediaControlGattServiceInterface.TRACK_POSITION_UNAVAILABLE); PlaybackState.Builder bob = new PlaybackState.Builder(mMockMediaData.state); bob.setState(state, position, playback_speed); @@ -272,11 +260,11 @@ public class MediaControlProfileTest { verify(mMockMediaPlayerWrapper, timeout(100).times(times)).seekTo(positionCaptor.capture()); // position cannot be negative and bigger than track duration - if (position < 0) Assert.assertEquals(positionCaptor.getValue().longValue(), 0); + if (position < 0) assertThat(positionCaptor.getValue().longValue()).isEqualTo(0); else if (position > duration) { - Assert.assertEquals(positionCaptor.getValue().longValue(), duration); + assertThat(positionCaptor.getValue().longValue()).isEqualTo(duration); } else { - Assert.assertEquals(positionCaptor.getValue().longValue(), position); + assertThat(positionCaptor.getValue().longValue()).isEqualTo(position); } } @@ -362,7 +350,7 @@ public class MediaControlProfileTest { verify(mMockMediaPlayerWrapper, timeout(100)).fastForward(); mMockMetadata.duration = Long.toString(duration); - Assert.assertEquals(duration, mMediaControlProfile.getCurrentTrackDuration()); + assertThat(mMediaControlProfile.getCurrentTrackDuration()).isEqualTo(duration); request = new Request(Request.Opcodes.MOVE_RELATIVE, 100); mMcpServiceCallbacks.onMediaControlRequest(request); verify(mMockMediaPlayerWrapper, timeout(100)).seekTo(duration); @@ -398,8 +386,8 @@ public class MediaControlProfileTest { | PlaybackState.ACTION_FAST_FORWARD | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS; - Assert.assertEquals( - actions | baseFeatures, mMediaControlProfile.getCurrentPlayerSupportedActions()); + assertThat(mMediaControlProfile.getCurrentPlayerSupportedActions()) + .isEqualTo(actions | baseFeatures); } @Test @@ -423,15 +411,15 @@ public class MediaControlProfileTest { | Request.SupportedOpcodes.FAST_FORWARD | Request.SupportedOpcodes.MOVE_RELATIVE; - Assert.assertEquals( - mMediaControlProfile.playerActions2McsSupportedOpcodes(actions), opcodes_supported); + assertThat(mMediaControlProfile.playerActions2McsSupportedOpcodes(actions)) + .isEqualTo(opcodes_supported); // Verify toggle-style play/pause control support actions = PlaybackState.ACTION_PLAY_PAUSE; opcodes_supported = Request.SupportedOpcodes.PAUSE | Request.SupportedOpcodes.PLAY; - Assert.assertEquals( - mMediaControlProfile.playerActions2McsSupportedOpcodes(actions), opcodes_supported); + assertThat(mMediaControlProfile.playerActions2McsSupportedOpcodes(actions)) + .isEqualTo(opcodes_supported); } @Test @@ -481,7 +469,7 @@ public class MediaControlProfileTest { PlayingOrder expected_value, boolean is_shuffle_set, boolean is_repeat_set) { doReturn(is_shuffle_set).when(mMockMediaPlayerWrapper).isShuffleSet(); doReturn(is_repeat_set).when(mMockMediaPlayerWrapper).isRepeatSet(); - Assert.assertEquals(expected_value, mMediaControlProfile.getCurrentPlayerPlayingOrder()); + assertThat(mMediaControlProfile.getCurrentPlayerPlayingOrder()).isEqualTo(expected_value); } @Test @@ -503,8 +491,8 @@ public class MediaControlProfileTest { doReturn(is_shuffle_set).when(mMockMediaPlayerWrapper).isShuffleSupported(); doReturn(is_repeat_set).when(mMockMediaPlayerWrapper).isRepeatSupported(); - Assert.assertEquals( - expected_value, mMediaControlProfile.getSupportedPlayingOrder().intValue()); + assertThat(mMediaControlProfile.getSupportedPlayingOrder().intValue()) + .isEqualTo(expected_value); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java index 77163fa53b..aeff386385 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java @@ -254,12 +254,12 @@ public class BluetoothOppManagerTest { public void cleanUpSendingFileInfo_fileInfoCleaned() { BluetoothOppUtility.sSendFileMap.clear(); Uri uri = Uri.parse("content:///a/new/folder/abc/xyz.txt"); - assertThat(BluetoothOppUtility.sSendFileMap.size()).isEqualTo(0); + assertThat(BluetoothOppUtility.sSendFileMap).isEmpty(); BluetoothOppManager.getInstance(mContext) .saveSendingFileInfo("text/plain", uri.toString(), false, true); assertThat(BluetoothOppUtility.sSendFileMap.size()).isEqualTo(1); BluetoothOppManager.getInstance(mContext).cleanUpSendingFileInfo(); - assertThat(BluetoothOppUtility.sSendFileMap.size()).isEqualTo(0); + assertThat(BluetoothOppUtility.sSendFileMap).isEmpty(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java index 2183c19347..935c1bf471 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java @@ -61,7 +61,6 @@ public class BluetoothOppServiceCleanupTest { BluetoothOppService service = null; try { service = new BluetoothOppService(adapterService); - service.start(); service.setAvailable(true); // Call stop while UpdateThread is running. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java index 7e54701383..dd14319b17 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java @@ -81,7 +81,6 @@ public class BluetoothOppServiceTest { AdapterService adapterService = new AdapterService(mTargetContext); mService = new BluetoothOppService(adapterService); - mService.start(); mService.setAvailable(true); mIsBluetoothOppServiceStarted = true; diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java index d10246229b..76fd28de89 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java @@ -319,7 +319,7 @@ public class BluetoothOppUtilityTest { assertThat(info.mCurrentBytes).isEqualTo(currentBytesValue); assertThat(info.mTimeStamp).isEqualTo(timestampValue); assertThat(info.mDestAddr).isEqualTo(destinationValue); - assertThat(info.mFileUri).isEqualTo(null); + assertThat(info.mFileUri).isNull(); assertThat(info.mFileType).isEqualTo(fileTypeValue); assertThat(info.mDeviceName).isEqualTo(deviceNameValue); assertThat(info.mHandoverInitiated).isEqualTo(false); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java index d2fddd8078..37927d28ec 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java @@ -32,6 +32,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.net.TetheringInterface; +import android.net.TetheringManager; import android.os.UserManager; import androidx.test.InstrumentationRegistry; @@ -55,15 +56,6 @@ import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) public class PanServiceTest { - private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; - private static final byte[] REMOTE_DEVICE_ADDRESS_AS_ARRAY = new byte[] {0, 0, 0, 0, 0, 0}; - - private static final int TIMEOUT_MS = 5_000; - - private PanService mService = null; - private BluetoothAdapter mAdapter = null; - private BluetoothDevice mRemoteDevice; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @@ -71,31 +63,34 @@ public class PanServiceTest { @Mock private PanNativeInterface mNativeInterface; @Mock private UserManager mMockUserManager; + private static final byte[] REMOTE_DEVICE_ADDRESS_AS_ARRAY = new byte[] {0, 0, 0, 0, 0, 0}; + + private static final int TIMEOUT_MS = 5_000; + + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mRemoteDevice = TestUtils.getTestDevice(mAdapter, 0); + private final Context mTargetContext = InstrumentationRegistry.getTargetContext(); + + private PanService mService; + @Before - public void setUp() throws Exception { - Context targetContext = InstrumentationRegistry.getTargetContext(); - TestUtils.setAdapterService(mAdapterService); + public void setUp() { + doReturn(mTargetContext.getResources()).when(mAdapterService).getResources(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); - PanNativeInterface.setInstance(mNativeInterface); - mService = new PanService(targetContext); - mService.start(); - mService.setAvailable(true); + TestUtils.mockGetSystemService( + mAdapterService, Context.USER_SERVICE, UserManager.class, mMockUserManager); + TestUtils.mockGetSystemService( + mAdapterService, Context.TETHERING_SERVICE, TetheringManager.class); - // Try getting the Bluetooth adapter - mAdapter = BluetoothAdapter.getDefaultAdapter(); - assertThat(mAdapter).isNotNull(); - mService.mUserManager = mMockUserManager; - mRemoteDevice = mAdapter.getRemoteDevice(REMOTE_DEVICE_ADDRESS); + mService = new PanService(mAdapterService, mNativeInterface); + mService.setAvailable(true); } @After - public void tearDown() throws Exception { + public void tearDown() { mService.stop(); mService.cleanup(); - PanNativeInterface.setInstance(null); - mService = PanService.getPanService(); - assertThat(mService).isNull(); - TestUtils.clearAdapterService(mAdapterService); + assertThat(PanService.getPanService()).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java index a1426dedef..5e4abee154 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java @@ -16,6 +16,8 @@ package com.android.bluetooth.pbap; +import static com.google.common.truth.Truth.assertThat; + import static org.mockito.Mockito.*; import android.bluetooth.BluetoothAdapter; @@ -31,9 +33,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; -import org.hamcrest.core.IsInstanceOf; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -97,11 +97,10 @@ public class PbapStateMachineTest { /** Test that initial state is WaitingForAuth */ @Test public void testInitialState() { - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTING, mPbapStateMachine.getConnectionState()); - Assert.assertThat( - mPbapStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(PbapStateMachine.WaitingForAuth.class)); + assertThat(mPbapStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_CONNECTING); + assertThat(mPbapStateMachine.getCurrentState()) + .isInstanceOf(PbapStateMachine.WaitingForAuth.class); } /** Test state transition from WaitingForAuth to Finished when the user rejected */ @@ -109,11 +108,10 @@ public class PbapStateMachineTest { @Test public void testStateTransition_WaitingForAuthToFinished() throws Exception { mPbapStateMachine.sendMessage(PbapStateMachine.REJECTED); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mPbapStateMachine.getConnectionState()); - Assert.assertThat( - mPbapStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(PbapStateMachine.Finished.class)); + assertThat(mPbapStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mPbapStateMachine.getCurrentState()) + .isInstanceOf(PbapStateMachine.Finished.class); } /** Test state transition from WaitingForAuth to Finished when the user rejected */ @@ -121,11 +119,10 @@ public class PbapStateMachineTest { @Test public void testStateTransition_WaitingForAuthToConnected() throws Exception { mPbapStateMachine.sendMessage(PbapStateMachine.AUTHORIZED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mPbapStateMachine.getConnectionState()); - Assert.assertThat( - mPbapStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(PbapStateMachine.Connected.class)); + assertThat(mPbapStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mPbapStateMachine.getCurrentState()) + .isInstanceOf(PbapStateMachine.Connected.class); } /** Test state transition from Connected to Finished when the OBEX server is done */ @@ -133,18 +130,16 @@ public class PbapStateMachineTest { @Test public void testStateTransition_ConnectedToFinished() throws Exception { mPbapStateMachine.sendMessage(PbapStateMachine.AUTHORIZED); - Assert.assertEquals( - BluetoothProfile.STATE_CONNECTED, mPbapStateMachine.getConnectionState()); - Assert.assertThat( - mPbapStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(PbapStateMachine.Connected.class)); + assertThat(mPbapStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_CONNECTED); + assertThat(mPbapStateMachine.getCurrentState()) + .isInstanceOf(PbapStateMachine.Connected.class); // PBAP OBEX transport is done. mPbapStateMachine.sendMessage(PbapStateMachine.DISCONNECT); - Assert.assertEquals( - BluetoothProfile.STATE_DISCONNECTED, mPbapStateMachine.getConnectionState()); - Assert.assertThat( - mPbapStateMachine.getCurrentState(), - IsInstanceOf.instanceOf(PbapStateMachine.Finished.class)); + assertThat(mPbapStateMachine.getConnectionState()) + .isEqualTo(BluetoothProfile.STATE_DISCONNECTED); + assertThat(mPbapStateMachine.getCurrentState()) + .isInstanceOf(PbapStateMachine.Finished.class); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java index f3e5ddd821..dfc93b3470 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java @@ -88,7 +88,7 @@ public class CallLogPullRequestTest { request.onPullComplete(); // No operation has been done. - assertThat(mCallCounter.size()).isEqualTo(0); + assertThat(mCallCounter).isEmpty(); } @Test @@ -102,7 +102,7 @@ public class CallLogPullRequestTest { request.onPullComplete(); // No operation has been done. - assertThat(mCallCounter.size()).isEqualTo(0); + assertThat(mCallCounter).isEmpty(); } @Test @@ -116,7 +116,7 @@ public class CallLogPullRequestTest { request.onPullComplete(); // Call counter should remain same. - assertThat(mCallCounter.size()).isEqualTo(0); + assertThat(mCallCounter).isEmpty(); } @Test @@ -140,7 +140,7 @@ public class CallLogPullRequestTest { request.onPullComplete(); // Call counter should remain same. - assertThat(mCallCounter.size()).isEqualTo(0); + assertThat(mCallCounter).isEmpty(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java index 41dac6b274..dfa4b854ea 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java @@ -533,8 +533,10 @@ public class PbapClientServiceTest { // Clean up and wait for it to complete PbapClientStateMachine sm = mMockDeviceMap.get(mRemoteDevice); assertThat(sm).isNotNull(); + + Looper looper = sm.getHandler().getLooper(); sm.disconnect(); - TestUtils.waitForLooperToFinishScheduledTask(sm.getHandler().getLooper()); + TestUtils.waitForLooperToFinishScheduledTask(looper); } // connect (device null) -> false diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java index 63a52d7ac4..6da23ea3f9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java @@ -18,17 +18,16 @@ package com.android.bluetooth.sap; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProfile; -import android.content.Context; import android.content.Intent; import android.os.Looper; import androidx.test.filters.MediumTest; -import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; @@ -47,40 +46,32 @@ import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) public class SapServiceTest { - private SapService mService = null; - private BluetoothAdapter mAdapter = null; - private Context mTargetContext; - @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; - private BluetoothDevice mDevice; + + private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter(); + private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 0); + + private SapService mService; @Before - public void setUp() throws Exception { - mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - TestUtils.setAdapterService(mAdapterService); + public void setUp() { + doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); if (Looper.myLooper() == null) { Looper.prepare(); } - mService = new SapService(mTargetContext); - mService.start(); + mService = new SapService(mAdapterService); mService.setAvailable(true); - // Try getting the Bluetooth adapter - mAdapter = BluetoothAdapter.getDefaultAdapter(); - assertThat(mAdapter).isNotNull(); - mDevice = TestUtils.getTestDevice(mAdapter, 0); } @After - public void tearDown() throws Exception { + public void tearDown() { mService.stop(); - mService = SapService.getSapService(); - assertThat(mService).isNull(); - TestUtils.clearAdapterService(mAdapterService); + assertThat(SapService.getSapService()).isNull(); } @Test @@ -89,22 +80,9 @@ public class SapServiceTest { assertThat(mService.getConnectedDevices()).isEmpty(); } - /** Test stop SAP Service */ - @Test - public void testStopSapService() throws Exception { - // SAP Service is already running: test stop(). Note: must be done on the main thread - InstrumentationRegistry.getInstrumentation() - .runOnMainSync( - () -> { - mService.stop(); - mService.start(); - }); - } - /** Test get connection policy for BluetoothDevice */ @Test public void testGetConnectionPolicy() { - when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.SAP)) .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); assertThat(mService.getConnectionPolicy(mDevice)) @@ -137,6 +115,6 @@ public class SapServiceTest { Intent intent = new Intent(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); intent.putExtra( BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, BluetoothDevice.REQUEST_TYPE_SIM_ACCESS); - mService.mSapReceiver.onReceive(mTargetContext, intent); + mService.mSapReceiver.onReceive(null, intent); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java b/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java index 3ed17fb529..2e49a1f6e1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java @@ -99,7 +99,7 @@ public class DipTest { boolean primaryRecord) { Intent intent = intentArgument.getValue(); - assertThat(intent).isNotEqualTo(null); + assertThat(intent).isNotNull(); assertThat(intent.getAction()).isEqualTo(BluetoothDevice.ACTION_SDP_RECORD); assertThat(device).isEqualTo(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)); assertThat(Utils.byteArrayToUuid(uuid)[0]) @@ -108,7 +108,7 @@ public class DipTest { .isEqualTo(intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1)); SdpDipRecord record = intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD); - assertThat(record).isNotEqualTo(null); + assertThat(record).isNotNull(); assertThat(specificationId).isEqualTo(record.getSpecificationId()); assertThat(vendorId).isEqualTo(record.getVendorId()); assertThat(vendorIdSource).isEqualTo(record.getVendorIdSource()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java index 798984b273..4aca68e62e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java @@ -41,7 +41,6 @@ import com.android.bluetooth.btservice.AdapterService; import com.google.common.primitives.Bytes; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -189,13 +188,12 @@ public class TbsGattTest { } else { assertThat(mTbsGatt.setBearerProviderName((String) value)).isFalse(); } - Assert.assertEquals((String) value, characteristic.getStringValue(0)); + assertThat(characteristic.getStringValue(0)).isEqualTo((String) value); } else if (characteristic.getUuid().equals(TbsGatt.UUID_BEARER_TECHNOLOGY)) { assertThat(mTbsGatt.setBearerTechnology((Integer) value)).isTrue(); - Assert.assertEquals( - (Integer) value, - characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)); + assertThat(characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)) + .isEqualTo((Integer) value); } else if (characteristic .getUuid() @@ -209,7 +207,7 @@ public class TbsGattTest { assertThat(mTbsGatt.setBearerUriSchemesSupportedList((List<String>) value)) .isFalse(); } - Assert.assertEquals(valueString, characteristic.getStringValue(0)); + assertThat(characteristic.getStringValue(0)).isEqualTo(valueString); } else if (characteristic.getUuid().equals(TbsGatt.UUID_STATUS_FLAGS)) { Pair<Integer, Boolean> flagStatePair = (Pair<Integer, Boolean>) value; @@ -252,14 +250,15 @@ public class TbsGattTest { assertThat(mTbsGatt.setTerminationReason(indexReasonPair.first, indexReasonPair.second)) .isTrue(); assertThat(characteristic.getValue()) - .asList() - .containsExactly( - indexReasonPair.first.byteValue(), indexReasonPair.second.byteValue()) - .inOrder(); + .isEqualTo( + new byte[] { + indexReasonPair.first.byteValue(), + indexReasonPair.second.byteValue() + }); } else if (characteristic.getUuid().equals(TbsGatt.UUID_INCOMING_CALL)) { if (value == null) { assertThat(mTbsGatt.clearIncomingCall()).isTrue(); - Assert.assertEquals(0, characteristic.getValue().length); + assertThat(characteristic.getValue()).isEmpty(); } else { Pair<Integer, String> indexStrPair = (Pair<Integer, String>) value; assertThat(mTbsGatt.setIncomingCall(indexStrPair.first, indexStrPair.second)) @@ -274,7 +273,7 @@ public class TbsGattTest { } else if (characteristic.getUuid().equals(TbsGatt.UUID_CALL_FRIENDLY_NAME)) { if (value == null) { assertThat(mTbsGatt.clearFriendlyName()).isTrue(); - Assert.assertEquals(0, characteristic.getValue().length); + assertThat(characteristic.getValue()).isEmpty(); } else { Pair<Integer, String> indexNamePair = (Pair<Integer, String>) value; assertThat(mTbsGatt.setCallFriendlyName(indexNamePair.first, indexNamePair.second)) diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java index d7ed9eee6c..79cba910c2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java @@ -247,8 +247,8 @@ public class TbsGenericTest { TbsCall capturedTbsCall = capturedCurrentCalls.get(capturedCallIndex); assertThat(capturedTbsCall).isNotNull(); assertThat(capturedTbsCall.getState()).isEqualTo(BluetoothLeCall.STATE_INCOMING); - assertThat(capturedTbsCall.getUri()).isEqualTo(null); - assertThat(capturedTbsCall.getSafeUri()).isEqualTo(null); + assertThat(capturedTbsCall.getUri()).isNull(); + assertThat(capturedTbsCall.getSafeUri()).isNull(); assertThat(capturedTbsCall.getFlags()).isEqualTo(0); assertThat(capturedTbsCall.isIncoming()).isTrue(); assertThat(capturedTbsCall.getFriendlyName()).isEqualTo("aFriendlyCaller"); @@ -283,9 +283,9 @@ public class TbsGenericTest { ArgumentCaptor<Map> currentCallsCaptor = ArgumentCaptor.forClass(Map.class); verify(mTbsGatt).setCallState(currentCallsCaptor.capture()); Map<Integer, TbsCall> capturedCurrentCalls = currentCallsCaptor.getValue(); - assertThat(capturedCurrentCalls.size()).isEqualTo(0); + assertThat(capturedCurrentCalls).isEmpty(); verify(mTbsGatt).setBearerListCurrentCalls(currentCallsCaptor.capture()); - assertThat(capturedCurrentCalls.size()).isEqualTo(0); + assertThat(capturedCurrentCalls).isEmpty(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java index c0f275b149..905710138f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java @@ -51,7 +51,6 @@ import com.android.bluetooth.flags.Flags; import com.android.bluetooth.hfp.BluetoothHeadsetProxy; import com.android.bluetooth.tbs.BluetoothLeCallControlProxy; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -172,7 +171,7 @@ public class BluetoothInCallServiceTest { doReturn(fakePhoneAccount).when(mMockCallInfo).getBestPhoneAccount(); String networkOperator = mBluetoothInCallService.getNetworkOperator(); - Assert.assertEquals(networkOperator, "label0"); + assertThat(networkOperator).isEqualTo("label0"); } @Test @@ -181,7 +180,7 @@ public class BluetoothInCallServiceTest { doReturn(fakeOperator).when(mMockTelephonyManager).getNetworkOperatorName(); String networkOperator = mBluetoothInCallService.getNetworkOperator(); - Assert.assertEquals(networkOperator, fakeOperator); + assertThat(networkOperator).isEqualTo(fakeOperator); } @Test @@ -190,7 +189,7 @@ public class BluetoothInCallServiceTest { doReturn(fakePhoneAccount).when(mMockCallInfo).getBestPhoneAccount(); String subscriberNumber = mBluetoothInCallService.getSubscriberNumber(); - Assert.assertEquals(subscriberNumber, TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX); + assertThat(subscriberNumber).isEqualTo(TEST_ACCOUNT_ADDRESS + TEST_ACCOUNT_INDEX); } @Test @@ -199,7 +198,7 @@ public class BluetoothInCallServiceTest { doReturn(fakeNumber).when(mMockTelephonyManager).getLine1Number(); String subscriberNumber = mBluetoothInCallService.getSubscriberNumber(); - Assert.assertEquals(subscriberNumber, fakeNumber); + assertThat(subscriberNumber).isEqualTo(fakeNumber); } @Test @@ -253,12 +252,12 @@ public class BluetoothInCallServiceTest { BluetoothCallQualityReport report = (BluetoothCallQualityReport) bundle.get(BluetoothCallQualityReport.EXTRA_BLUETOOTH_CALL_QUALITY_REPORT); - Assert.assertEquals(10, report.getSentTimestampMillis()); - Assert.assertEquals(20, report.getRssiDbm()); - Assert.assertEquals(30, report.getSnrDb()); - Assert.assertEquals(40, report.getRetransmittedPacketsCount()); - Assert.assertEquals(50, report.getPacketsNotReceivedCount()); - Assert.assertEquals(60, report.getNegativeAcknowledgementCount()); + assertThat(report.getSentTimestampMillis()).isEqualTo(10); + assertThat(report.getRssiDbm()).isEqualTo(20); + assertThat(report.getSnrDb()).isEqualTo(30); + assertThat(report.getRetransmittedPacketsCount()).isEqualTo(40); + assertThat(report.getPacketsNotReceivedCount()).isEqualTo(50); + assertThat(report.getNegativeAcknowledgementCount()).isEqualTo(60); } @Test @@ -907,7 +906,7 @@ public class BluetoothInCallServiceTest { // parent call arrived, but children have not, then do inference on children calls.add(conferenceCall); - Assert.assertEquals(calls.size(), 1); + assertThat(calls.size()).isEqualTo(1); mBluetoothInCallService.onCallAdded(conferenceCall); clearInvocations(mMockBluetoothHeadset); @@ -946,7 +945,7 @@ public class BluetoothInCallServiceTest { mBluetoothInCallService.onCallRemoved(holdingCall, true); calls.remove(activeCall); calls.remove(holdingCall); - Assert.assertEquals(calls.size(), 1); + assertThat(calls.size()).isEqualTo(1); clearInvocations(mMockBluetoothHeadset); mBluetoothInCallService.listCurrentCalls(); @@ -1042,7 +1041,7 @@ public class BluetoothInCallServiceTest { // parent call arrived, but children have not, then do inference on children calls.add(conferenceCall); - Assert.assertEquals(calls.size(), 1); + assertThat(calls.size()).isEqualTo(1); mBluetoothInCallService.onCallAdded(conferenceCall); clearInvocations(mMockBluetoothHeadset); @@ -1080,7 +1079,7 @@ public class BluetoothInCallServiceTest { mBluetoothInCallService.onCallRemoved(activeCall_1, true); doReturn(false).when(activeCall_1).isConference(); calls.remove(activeCall_1); - Assert.assertEquals(calls.size(), 2); + assertThat(calls.size()).isEqualTo(2); // Call 2 removed from conf doReturn(cause).when(activeCall_2).getDisconnectCause(); @@ -1690,134 +1689,116 @@ public class BluetoothInCallServiceTest { doReturn(TelephonyManager.NETWORK_TYPE_GSM) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_GSM); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_GSM); doReturn(TelephonyManager.NETWORK_TYPE_GPRS) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_2G); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_2G); doReturn(TelephonyManager.NETWORK_TYPE_EVDO_B) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_3G); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_3G); doReturn(TelephonyManager.NETWORK_TYPE_TD_SCDMA) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_WCDMA); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_WCDMA); doReturn(TelephonyManager.NETWORK_TYPE_LTE) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_LTE); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_LTE); doReturn(TelephonyManager.NETWORK_TYPE_1xRTT) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_CDMA); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_CDMA); doReturn(TelephonyManager.NETWORK_TYPE_HSPAP) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_4G); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_4G); doReturn(TelephonyManager.NETWORK_TYPE_IWLAN) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_WIFI); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_WIFI); doReturn(TelephonyManager.NETWORK_TYPE_NR).when(mMockTelephonyManager).getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_5G); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_5G); doReturn(TelephonyManager.NETWORK_TYPE_LTE_CA) .when(mMockTelephonyManager) .getDataNetworkType(); - Assert.assertEquals( - mBluetoothInCallService.getBearerTechnology(), - BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_GSM); + assertThat(mBluetoothInCallService.getBearerTechnology()) + .isEqualTo(BluetoothLeCallControlProxy.BEARER_TECHNOLOGY_GSM); } @Test public void getTbsTerminationReason() { BluetoothCall call = getMockCall(UUID.randomUUID()); - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_FAIL); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_FAIL); DisconnectCause cause = new DisconnectCause(DisconnectCause.BUSY, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_LINE_BUSY); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_LINE_BUSY); cause = new DisconnectCause(DisconnectCause.REJECTED, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_REMOTE_HANGUP); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_REMOTE_HANGUP); cause = new DisconnectCause(DisconnectCause.LOCAL, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); mBluetoothInCallService.mIsTerminatedByClient = false; - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_SERVER_HANGUP); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_SERVER_HANGUP); cause = new DisconnectCause(DisconnectCause.LOCAL, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); mBluetoothInCallService.mIsTerminatedByClient = true; - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_CLIENT_HANGUP); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_CLIENT_HANGUP); cause = new DisconnectCause(DisconnectCause.ERROR, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_NETWORK_CONGESTION); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_NETWORK_CONGESTION); cause = new DisconnectCause( DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_INVALID_URI); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_INVALID_URI); cause = new DisconnectCause(DisconnectCause.ERROR, null, null, null, 1); doReturn(cause).when(call).getDisconnectCause(); - Assert.assertEquals( - mBluetoothInCallService.getTbsTerminationReason(call), - BluetoothLeCallControl.TERMINATION_REASON_NETWORK_CONGESTION); + assertThat(mBluetoothInCallService.getTbsTerminationReason(call)) + .isEqualTo(BluetoothLeCallControl.TERMINATION_REASON_NETWORK_CONGESTION); } @Test public void onDestroy() { - assertThat(mBluetoothInCallService.mOnCreateCalled).isTrue(); + assertThat(BluetoothInCallService.getInstance()).isNotNull(); mBluetoothInCallService.onDestroy(); - assertThat(mBluetoothInCallService.mOnCreateCalled).isFalse(); + assertThat(BluetoothInCallService.getInstance()).isNull(); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java index 3e912701f6..69d4407b23 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java @@ -58,6 +58,7 @@ import android.media.AudioManager; import android.os.Binder; import android.os.ParcelUuid; import android.os.test.TestLooper; +import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; @@ -461,7 +462,8 @@ public class VolumeControlServiceTest { } @Test - public void volumeCache() { + @DisableFlags(Flags.FLAG_VCP_DEVICE_VOLUME_API_IMPROVEMENTS) + public void volumeCacheDeprecated() { int groupId = 1; int volume = 6; @@ -478,6 +480,56 @@ public class VolumeControlServiceTest { } @Test + @EnableFlags(Flags.FLAG_VCP_DEVICE_VOLUME_API_IMPROVEMENTS) + public void volumeCache() { + int groupId = 1; + int groupVolume = 6; + int devOneVolume = 20; + int devTwoVolume = 30; + + // Both devices are in the same group + when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); + when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); + when(mCsipService.getGroupDevicesOrdered(groupId)) + .thenReturn(Arrays.asList(mDevice, mDeviceTwo)); + + assertThat(mService.getGroupVolume(groupId)).isEqualTo(VOLUME_CONTROL_UNKNOWN_VOLUME); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(VOLUME_CONTROL_UNKNOWN_VOLUME); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(VOLUME_CONTROL_UNKNOWN_VOLUME); + + // Set group volume + mService.setGroupVolume(groupId, groupVolume); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(groupVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(groupVolume); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(groupVolume); + + // Send autonomous volume change. + int autonomousVolume = 10; + generateVolumeStateChanged(null, groupId, autonomousVolume, 0, false, true); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(autonomousVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(autonomousVolume); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(autonomousVolume); + + // Set first device volume + mService.setDeviceVolume(mDevice, devOneVolume, false); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(autonomousVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(devOneVolume); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(autonomousVolume); + + // Set second device volume + mService.setDeviceVolume(mDeviceTwo, devTwoVolume, false); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(autonomousVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(devOneVolume); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(devTwoVolume); + + // Set group volume again + mService.setGroupVolume(groupId, groupVolume); + assertThat(mService.getGroupVolume(groupId)).isEqualTo(groupVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(groupVolume); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(groupVolume); + } + + @Test public void activeGroupChange() { int groupId_1 = 1; int volume_groupId_1 = 6; @@ -509,7 +561,8 @@ public class VolumeControlServiceTest { } @Test - public void muteCache() { + @DisableFlags(Flags.FLAG_VCP_DEVICE_VOLUME_API_IMPROVEMENTS) + public void muteCacheDeprecated() { int groupId = 1; int volume = 6; @@ -531,6 +584,61 @@ public class VolumeControlServiceTest { assertThat(mService.getGroupMute(groupId)).isFalse(); } + @Test + @EnableFlags(Flags.FLAG_VCP_DEVICE_VOLUME_API_IMPROVEMENTS) + public void muteCache() { + int groupId = 1; + int groupVolume = 6; + + // Both devices are in the same group + when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId); + when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId); + when(mCsipService.getGroupDevicesOrdered(groupId)) + .thenReturn(Arrays.asList(mDevice, mDeviceTwo)); + + assertThat(mService.getGroupMute(groupId)).isFalse(); + assertThat(mService.getMute(mDevice)).isFalse(); + assertThat(mService.getMute(mDeviceTwo)).isFalse(); + + // Send autonomous volume change + generateVolumeStateChanged(null, groupId, groupVolume, 0, false, true); + + // Mute + mService.muteGroup(groupId); + assertThat(mService.getGroupMute(groupId)).isTrue(); + assertThat(mService.getMute(mDevice)).isTrue(); + assertThat(mService.getMute(mDeviceTwo)).isTrue(); + + // Make sure the volume is kept even when muted + assertThat(mService.getGroupVolume(groupId)).isEqualTo(groupVolume); + assertThat(mService.getDeviceVolume(mDevice)).isEqualTo(groupVolume); + assertThat(mService.getDeviceVolume(mDeviceTwo)).isEqualTo(groupVolume); + + // Send autonomous unmute + generateVolumeStateChanged(null, groupId, groupVolume, 0, false, true); + assertThat(mService.getGroupMute(groupId)).isFalse(); + assertThat(mService.getMute(mDevice)).isFalse(); + assertThat(mService.getMute(mDeviceTwo)).isFalse(); + + // Mute first device + mService.mute(mDevice); + assertThat(mService.getGroupMute(groupId)).isFalse(); + assertThat(mService.getMute(mDevice)).isTrue(); + assertThat(mService.getMute(mDeviceTwo)).isFalse(); + + // Mute second device + mService.mute(mDeviceTwo); + assertThat(mService.getGroupMute(groupId)).isFalse(); + assertThat(mService.getMute(mDevice)).isTrue(); + assertThat(mService.getMute(mDeviceTwo)).isTrue(); + + // Unmute group should unmute devices even if group is unmuted + mService.unmuteGroup(groupId); + assertThat(mService.getGroupMute(groupId)).isFalse(); + assertThat(mService.getMute(mDevice)).isFalse(); + assertThat(mService.getMute(mDeviceTwo)).isFalse(); + } + /** Test Volume Control with muted stream. */ @Test public void volumeChangeWhileMuted() { @@ -612,6 +720,14 @@ public class VolumeControlServiceTest { InOrder inOrderAudio = inOrder(mAudioManager); inOrderAudio.verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); + InOrder inOrderNative = inOrder(mNativeInterface); + if (Flags.vcpDeviceVolumeApiImprovements()) { + // AF always call setVolume via LeAudioService at first connected remote from group + mService.setGroupVolume(groupId, 123); + // It should be ignored and not set to native + inOrderNative.verify(mNativeInterface, never()).setGroupVolume(anyInt(), anyInt()); + } + // Make device Active now. This will trigger setting volume to AF when(mLeAudioService.getActiveGroupId()).thenReturn(groupId); mService.setGroupActive(groupId, true); @@ -634,7 +750,11 @@ public class VolumeControlServiceTest { initialAutonomousFlag); inOrderAudio.verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); - verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volumeDevice)); + if (Flags.vcpDeviceVolumeApiImprovements()) { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volumeDevice)); + } else { + inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volumeDevice)); + } } private void testConnectedDeviceWithResetFlag( @@ -676,6 +796,10 @@ public class VolumeControlServiceTest { InOrder inOrderAudio = inOrder(mAudioManager); inOrderAudio.verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); InOrder inOrderNative = inOrder(mNativeInterface); + if (Flags.vcpDeviceVolumeApiImprovements()) { + // AF always call setVolume via LeAudioService at first connected remote from group + mService.setGroupVolume(groupId, expectedAfVol); + } inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(expectedAfVol)); // Make device Active now. This will trigger setting volume to AF @@ -698,7 +822,11 @@ public class VolumeControlServiceTest { initialAutonomousFlag); inOrderAudio.verify(mAudioManager, never()).setStreamVolume(anyInt(), anyInt(), anyInt()); - inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(expectedAfVol)); + if (Flags.vcpDeviceVolumeApiImprovements()) { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(expectedAfVol)); + } else { + inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(expectedAfVol)); + } } /** Test if phone will set volume which is read from the buds */ @@ -742,8 +870,12 @@ public class VolumeControlServiceTest { assertThat(mService.getDevices()).contains(mDeviceTwo); generateVolumeStateChanged(mDeviceTwo, LE_AUDIO_GROUP_ID_INVALID, volume_2, 0, false, true); - inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); - inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); + if (Flags.vcpDeviceVolumeApiImprovements()) { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); + } else { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); + inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); + } } /** @@ -817,9 +949,14 @@ public class VolumeControlServiceTest { generateVolumeStateChanged(mDeviceTwo, LE_AUDIO_GROUP_ID_INVALID, volume_2, 0, false, true); // Check if new device was muted - inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volume)); - inOrderNative.verify(mNativeInterface).mute(eq(mDeviceTwo)); - inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); + if (Flags.vcpDeviceVolumeApiImprovements()) { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volume)); + inOrderNative.verify(mNativeInterface).mute(eq(mDeviceTwo)); + } else { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(volume)); + inOrderNative.verify(mNativeInterface).mute(eq(mDeviceTwo)); + inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(volume)); + } } /** @@ -1064,8 +1201,12 @@ public class VolumeControlServiceTest { generateVolumeStateChanged( mDeviceTwo, LE_AUDIO_GROUP_ID_INVALID, groupVolume, 0, false, true); - inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); - inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); + if (Flags.vcpDeviceVolumeApiImprovements()) { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); + } else { + inOrderNative.verify(mNativeInterface).setVolume(eq(mDeviceTwo), eq(groupVolume)); + inOrderNative.verify(mNativeInterface).setGroupVolume(eq(groupId), eq(groupVolume)); + } // Generate events for both devices generateDeviceOffsetChangedMessageFromNative(mDevice, 1, 100); diff --git a/android/leaudio/app/src/androidTest/java/com/android/bluetooth/leaudio/ExampleInstrumentedTest.java b/android/leaudio/app/src/androidTest/java/com/android/bluetooth/leaudio/ExampleInstrumentedTest.java deleted file mode 100644 index 48e81bb636..0000000000 --- a/android/leaudio/app/src/androidTest/java/com/android/bluetooth/leaudio/ExampleInstrumentedTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.android.bluetooth.leaudio; - -import static org.junit.Assert.assertEquals; - -import android.content.Context; - -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.android.bluetooth.leaudio", appContext.getPackageName()); - } -} diff --git a/android/leaudio/app/src/test/java/pl/codecoup/ehima/leaudio/ExampleUnitTest.java b/android/leaudio/app/src/test/java/pl/codecoup/ehima/leaudio/ExampleUnitTest.java deleted file mode 100644 index 53e6ef47b3..0000000000 --- a/android/leaudio/app/src/test/java/pl/codecoup/ehima/leaudio/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.android.bluetooth.leaudio; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see <a href="http://d.android.com/tools/testing">Testing documentation</a> - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} diff --git a/android/pandora/gen_cov.py b/android/pandora/gen_cov.py index b3d85b32d6..ba62530633 100755 --- a/android/pandora/gen_cov.py +++ b/android/pandora/gen_cov.py @@ -310,8 +310,8 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument( '--apex-name', - default='com.android.btservices', - help='bluetooth apex name. Default: com.android.btservices') + default='com.android.bt', + help='bluetooth apex name. Default: com.android.bt') parser.add_argument( '--java', action='store_true', help='generate Java coverage') parser.add_argument( diff --git a/android/pandora/server/configs/PtsBotTestMts.xml b/android/pandora/server/configs/PtsBotTestMts.xml index 168eee7dea..00fb46bfbd 100644 --- a/android/pandora/server/configs/PtsBotTestMts.xml +++ b/android/pandora/server/configs/PtsBotTestMts.xml @@ -73,7 +73,7 @@ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/android/pandora/test/main.py b/android/pandora/test/main.py index d8eadf1e60..d0018b28d3 100644 --- a/android/pandora/test/main.py +++ b/android/pandora/test/main.py @@ -4,18 +4,18 @@ site.main() import argparse import logging +import itertools import os import sys from argparse import Namespace from mobly import suite_runner -from typing import List, Tuple +from typing import List, Tuple, Union, Literal _BUMBLE_BTSNOOP_FMT = 'bumble_btsnoop_{pid}_{instance}.log' -import a2dp_test - # Import test cases modules. +import a2dp_test import aics_test import asha_test import avatar.cases.host_test @@ -25,12 +25,55 @@ import avatar.cases.security_test import gatt_test import hap_test import hfpclient_test -from pairing import _test_class_list as _pairing_test_class_list import sdp_test +from pairing import _test_class_list as _pairing_test_class_list +from pandora.host_pb2 import PrimaryPhy, PRIMARY_1M, PRIMARY_CODED + + +class LeHostTestFiltered(avatar.cases.le_host_test.LeHostTest): + """ + LeHostTestFiltered inherits from LeHostTest to skip currently broken and unfeasible to fix tests. + Overridden tests will be visible as PASS when run. + """ + skipped_tests = [ + # Reason for skipping tests: b/272120114 + "test_extended_scan('non_connectable_scannable','directed',150,0)", + "test_extended_scan('non_connectable_scannable','undirected',150,0)", + "test_extended_scan('non_connectable_scannable','directed',150,2)", + "test_extended_scan('non_connectable_scannable','undirected',150,2)", + ] + + @avatar.parameterized( + *itertools.product( + # The advertisement cannot be both connectable and scannable. + ('connectable', 'non_connectable', 'non_connectable_scannable'), + ('directed', 'undirected'), + # Bumble does not send multiple HCI commands, so it must also fit in + # 1 HCI command (max length 251 minus overhead). + (0, 150), + (PRIMARY_1M, PRIMARY_CODED), + ),) # type: ignore[misc] + def test_extended_scan( + self, + connectable_scannable: Union[Literal['connectable'], Literal['non_connectable'], + Literal['non_connectable_scannable']], + directed: Union[Literal['directed'], Literal['undirected']], + data_len: int, + primary_phy: PrimaryPhy, + ) -> None: + current_test = f"test_extended_scan('{connectable_scannable}','{directed}',{data_len},{primary_phy})" + logging.info(f"current test: {current_test}") + if current_test not in self.skipped_tests: + if current_test in avatar.cases.le_host_test.LeHostTest.__dict__: + avatar.cases.le_host_test.LeHostTest.__dict__[current_test](self) + else: + logging.info(f"TEST: {current_test} NOT FOUND") + + _TEST_CLASSES_LIST = [ avatar.cases.host_test.HostTest, - avatar.cases.le_host_test.LeHostTest, + LeHostTestFiltered, avatar.cases.security_test.SecurityTest, avatar.cases.le_security_test.LeSecurityTest, a2dp_test.A2dpTest, diff --git a/apex/Android.bp b/apex/Android.bp index 4eccda2a11..d8f4603a8c 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -23,39 +23,14 @@ linker_config { } // Legacy Bluetooth apex prior to Baklava +// This is kept for soong purposes but this apex doesn't do anything anymore // TODO b/383863941 delete apex { + enabled: false, name: "com.android.btservices", defaults: ["t-launched-apex-module"], manifest: "apex_manifest.json", - bootclasspath_fragments: ["com.android.btservices-bootclasspath-fragment"], - systemserverclasspath_fragments: ["com.android.btservices-systemserverclasspath-fragment"], - compat_configs: [ - "bluetooth-compat-config", - "bluetoothapk-platform-compat-config", - "framework-bluetooth-compat-config", - ], - apps: ["Bluetooth"], - multilib: { - first: { - // Extractor process runs only with the primary ABI. - jni_libs: [ - "libbluetooth_jni", - ], - }, - }, - - prebuilts: [ - "audio_set_configurations_bfbs", - "audio_set_configurations_json", - "audio_set_scenarios_bfbs", - "audio_set_scenarios_json", - "bt_did.conf", - "bt_stack.conf", - "btservices-linker-config", - "interop_database.conf", - ], key: "com.android.btservices.key", certificate: ":com.android.btservices.certificate", updatable: true, @@ -74,71 +49,6 @@ android_app_certificate { certificate: "com.android.btservices", } -sdk { - name: "btservices-module-sdk", - apexes: [ - // Adds exportable dependencies of the APEX to the sdk, - // e.g. *classpath_fragments. - "com.android.btservices", - ], -} - -// Encapsulate the contributions made by the com.android.bluetooth to the bootclasspath. -bootclasspath_fragment { - name: "com.android.btservices-bootclasspath-fragment", - contents: ["framework-bluetooth"], - apex_available: ["com.android.btservices"], - - // The bootclasspath_fragments that provide APIs on which this depends. - fragments: [ - { - apex: "com.android.art", - module: "art-bootclasspath-fragment", - }, - ], - - // Additional stubs libraries that this fragment's contents use which are - // not provided by another bootclasspath_fragment. - additional_stubs: [ - "android-non-updatable", - ], - - // Additional hidden API flag files to override the defaults. This must only be - // modified by the Soong or platform compat team. - hidden_api: { - max_target_o_low_priority: ["hiddenapi/hiddenapi-max-target-o-low-priority.txt"], - max_target_r_low_priority: ["hiddenapi/hiddenapi-max-target-r-low-priority.txt"], - unsupported: ["hiddenapi/hiddenapi-unsupported.txt"], - - // The following packages contain classes from other modules on the - // bootclasspath. That means that the hidden API flags for this module - // has to explicitly list every single class this module provides in - // that package to differentiate them from the classes provided by other - // modules. That can include private classes that are not part of the - // API. - split_packages: [ - "android.bluetooth", - ], - - // The following packages and all their subpackages currently only - // contain classes from this bootclasspath_fragment. Listing a package - // here won't prevent other bootclasspath modules from adding classes in - // any of those packages but it will prevent them from adding those - // classes into an API surface, e.g. public, system, etc.. Doing so will - // result in a build failure due to inconsistent flags. - package_prefixes: [ - "android.bluetooth.le", - "com.android.bluetooth", - ], - }, -} - -systemserverclasspath_fragment { - name: "com.android.btservices-systemserverclasspath-fragment", - standalone_contents: ["service-bluetooth"], - apex_available: ["com.android.btservices"], -} - // Mainline bluetooth apex module. apex { name: "com.android.bt", @@ -242,6 +152,6 @@ bootclasspath_fragment { systemserverclasspath_fragment { name: "com.android.bt-systemserverclasspath-fragment", - standalone_contents: ["service-bluetooth-new"], + standalone_contents: ["service-bluetooth"], apex_available: ["com.android.bt"], } diff --git a/common/Android.bp b/common/Android.bp index 900cc365d7..f472c9e3d0 100644 --- a/common/Android.bp +++ b/common/Android.bp @@ -22,7 +22,7 @@ java_library { "bluetooth/constants/aics/GainMode.aidl", "bluetooth/constants/aics/Mute.aidl", ], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", sdk_version: "module_current", visibility: ["//packages/modules/Bluetooth:__subpackages__"], diff --git a/flags/Android.bp b/flags/Android.bp index f43322d4ed..8a1dc66552 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -6,7 +6,7 @@ package { aconfig_declarations { name: "bluetooth_aconfig_flags", package: "com.android.bluetooth.flags", - container: "com.android.btservices", + container: "com.android.bt", visibility: ["//packages/modules/Bluetooth/framework"], // LINT.IfChange srcs: [ @@ -19,7 +19,6 @@ aconfig_declarations { "btif_dm.aconfig", "btm_ble.aconfig", "connectivity.aconfig", - "device_iot_config.aconfig", "dis.aconfig", "framework.aconfig", "gap.aconfig", @@ -59,7 +58,7 @@ java_aconfig_library { name: "bluetooth_flags_java_lib", aconfig_declarations: "bluetooth_aconfig_flags", visibility: ["//packages/modules/Bluetooth:__subpackages__"], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], libs: ["framework-configinfrastructure.stubs.module_lib"], sdk_version: "module_current", min_sdk_version: "Tiramisu", @@ -83,7 +82,7 @@ cc_aconfig_library { aconfig_declarations: "bluetooth_aconfig_flags", host_supported: true, visibility: ["//packages/modules/Bluetooth:__subpackages__"], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } @@ -101,7 +100,7 @@ rust_aconfig_library { host_supported: true, crate_name: "bluetooth_aconfig_flags_rust", aconfig_declarations: "bluetooth_aconfig_flags", - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", visibility: ["//packages/modules/Bluetooth/system:__subpackages__"], } diff --git a/flags/BUILD.gn b/flags/BUILD.gn index 6c7185a24a..9f96d85933 100644 --- a/flags/BUILD.gn +++ b/flags/BUILD.gn @@ -12,7 +12,6 @@ aconfig("bluetooth_flags_c_lib") { "btif_dm.aconfig", "btm_ble.aconfig", "connectivity.aconfig", - "device_iot_config.aconfig", "dis.aconfig", "framework.aconfig", "gap.aconfig", diff --git a/flags/a2dp.aconfig b/flags/a2dp.aconfig index e6275bf010..06d46a7f76 100644 --- a/flags/a2dp.aconfig +++ b/flags/a2dp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "bta_av_use_peer_codec" diff --git a/flags/active_device_manager.aconfig b/flags/active_device_manager.aconfig index fefcdd1d87..68ece5e73b 100644 --- a/flags/active_device_manager.aconfig +++ b/flags/active_device_manager.aconfig @@ -1,25 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" - -flag { - name: "adm_fallback_when_wired_audio_disconnected" - namespace: "bluetooth" - description: "Fallback to other connected device when wired audio device disconnects" - bug: "348124361" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { - name: "adm_always_fallback_to_available_device" - namespace: "bluetooth" - description: "Fix audio path and always fallback to available device" - bug: "351820274" - metadata { - purpose: PURPOSE_BUGFIX - } -} +container: "com.android.bt" flag { name: "adm_verify_active_fallback_device" diff --git a/flags/adapter.aconfig b/flags/adapter.aconfig index f355113fe0..f6bf65e1f6 100644 --- a/flags/adapter.aconfig +++ b/flags/adapter.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "adapter_properties_looper" diff --git a/flags/avrcp.aconfig b/flags/avrcp.aconfig index 5e806efb11..7a30583c07 100644 --- a/flags/avrcp.aconfig +++ b/flags/avrcp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "abs_volume_sdp_conflict" diff --git a/flags/avrcp_controller.aconfig b/flags/avrcp_controller.aconfig index 4374eef8fa..be732ee1ad 100644 --- a/flags/avrcp_controller.aconfig +++ b/flags/avrcp_controller.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "uncache_player_when_browsed_player_changes" diff --git a/flags/bta_dm.aconfig b/flags/bta_dm.aconfig index f35d562ebf..d91f3168b7 100644 --- a/flags/bta_dm.aconfig +++ b/flags/bta_dm.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "bta_dm_defer_device_discovery_state_change_until_rnr_complete" @@ -34,3 +34,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "extend_and_randomize_role_switch_delay" + namespace: "bluetooth" + description: "Fix the possible conflicts between role switch and authentication" + bug: "388459732" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/btif_dm.aconfig b/flags/btif_dm.aconfig index 2f16904b8f..b8802a9db1 100644 --- a/flags/btif_dm.aconfig +++ b/flags/btif_dm.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "bond_transport_after_bond_cancel_fix" diff --git a/flags/btm_ble.aconfig b/flags/btm_ble.aconfig index 0922fd1aa0..2413c74be1 100644 --- a/flags/btm_ble.aconfig +++ b/flags/btm_ble.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "floss_separate_host_privacy_and_llprivacy" diff --git a/flags/connectivity.aconfig b/flags/connectivity.aconfig index 80efed1aa2..10c9f417e2 100644 --- a/flags/connectivity.aconfig +++ b/flags/connectivity.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "api_get_connection_state_using_identity_address" diff --git a/flags/device_iot_config.aconfig b/flags/device_iot_config.aconfig deleted file mode 100644 index 77ede517d4..0000000000 --- a/flags/device_iot_config.aconfig +++ /dev/null @@ -1,9 +0,0 @@ -package: "com.android.bluetooth.flags" -container: "com.android.btservices" - -flag { - name: "device_iot_config_logging" - namespace: "bluetooth" - description: "Enable device IOT information storage." - bug: "290844229" -} diff --git a/flags/dis.aconfig b/flags/dis.aconfig index f96d6c3b5f..ace19bca21 100644 --- a/flags/dis.aconfig +++ b/flags/dis.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "queue_dis_requests" diff --git a/flags/framework.aconfig b/flags/framework.aconfig index ae23329345..757148b7df 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "support_metadata_device_types_apis" diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 0ef4a7aa20..7f0aa3c833 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "encrypted_advertising_data" diff --git a/flags/gatt.aconfig b/flags/gatt.aconfig index 55e5b27077..1b9bfb516e 100644 --- a/flags/gatt.aconfig +++ b/flags/gatt.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "default_gatt_transport" diff --git a/flags/hal.aconfig b/flags/hal.aconfig index 286d1fceb4..3e16fa5355 100644 --- a/flags/hal.aconfig +++ b/flags/hal.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "audio_port_binder_inherit_rt" @@ -19,4 +19,14 @@ flag { metadata { purpose: PURPOSE_BUGFIX } +} + +flag { + name: "snoop_logger_recreate_logs_directory" + namespace: "bluetooth" + description: "Recreate logs directory if removed" + bug: "383876267" + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/flags/hap.aconfig b/flags/hap.aconfig index 3ce320f88d..634000d0bd 100644 --- a/flags/hap.aconfig +++ b/flags/hap.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "aics_api" diff --git a/flags/hci.aconfig b/flags/hci.aconfig index 79da26788b..cdd5ca3ab6 100644 --- a/flags/hci.aconfig +++ b/flags/hci.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "encryption_change_v2" diff --git a/flags/hfp.aconfig b/flags/hfp.aconfig index 96985f2750..7b81b483b4 100644 --- a/flags/hfp.aconfig +++ b/flags/hfp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "auto_connect_on_multiple_hfp_when_no_a2dp_device" @@ -60,16 +60,6 @@ flag { } flag { - name: "headset_client_am_hf_volume_symmetric" - namespace: "bluetooth" - description: "Fix AM/HF volume conversion to be symmetric" - bug: "340482648" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "maintain_call_index_after_conference" namespace: "bluetooth" description: "Avoid change of clcc call index after call disconnects from conference" diff --git a/flags/hfpclient.aconfig b/flags/hfpclient.aconfig index ded90b3578..c134baac7e 100644 --- a/flags/hfpclient.aconfig +++ b/flags/hfpclient.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "hfp_client_disconnecting_state" diff --git a/flags/hid.aconfig b/flags/hid.aconfig index fa638ba092..17c66db035 100644 --- a/flags/hid.aconfig +++ b/flags/hid.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "allow_switching_hid_and_hogp" @@ -125,3 +125,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "disconnect_hid_channels_serially" + namespace: "bluetooth" + description: "Only disconnect control channel after interrupt channel disconnection is acked" + bug: "387937345" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/l2cap.aconfig b/flags/l2cap.aconfig index fb53c10bef..7e1ca0b016 100644 --- a/flags/l2cap.aconfig +++ b/flags/l2cap.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "l2cap_tx_complete_cb_info" diff --git a/flags/le_advertising.aconfig b/flags/le_advertising.aconfig index 524d0461e5..56f849ab7a 100644 --- a/flags/le_advertising.aconfig +++ b/flags/le_advertising.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "nrpa_non_connectable_adv" diff --git a/flags/leaudio.aconfig b/flags/leaudio.aconfig index 9c5132afd5..e7b0b2abcf 100644 --- a/flags/leaudio.aconfig +++ b/flags/leaudio.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "leaudio_broadcast_monitor_source_sync_status" @@ -441,3 +441,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "leaudio_sm_ignore_connect_events_in_connecting_state" + namespace: "bluetooth" + description: "When received CONNECT event in Connecting state, with no prior DISCONNECT - ignore the event" + bug: "384460395" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/mapclient.aconfig b/flags/mapclient.aconfig index 97d0411683..fe8f90d81d 100644 --- a/flags/mapclient.aconfig +++ b/flags/mapclient.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "handle_delivery_sending_failure_events" diff --git a/flags/mcp.aconfig b/flags/mcp.aconfig index 430bacd761..80567acae7 100644 --- a/flags/mcp.aconfig +++ b/flags/mcp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "mcp_allow_play_without_active_player" diff --git a/flags/metric.aconfig b/flags/metric.aconfig index f0c62e37fc..e8b8628ba2 100644 --- a/flags/metric.aconfig +++ b/flags/metric.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "bluetooth_power_telemetry" diff --git a/flags/opp.aconfig b/flags/opp.aconfig index bd0f380c45..1033aa4d29 100644 --- a/flags/opp.aconfig +++ b/flags/opp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "opp_ignore_content_observer_after_service_stop" diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig index 2788831a6a..ae3d19a6ac 100644 --- a/flags/pairing.aconfig +++ b/flags/pairing.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "clear_auth_collision_state_on_pairing_complete" @@ -22,16 +22,6 @@ flag { } flag { - name: "temporary_pairing_device_properties" - namespace: "bluetooth" - description: "Do not remove the device properties immediately after insecure pairing" - bug: "342202557" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "pairing_name_discovery_addresss_mismatch" namespace: "bluetooth" description: "Do not abort pairing if name discovery for a another device fails" @@ -240,3 +230,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "create_metadata_after_bonding" + namespace: "bluetooth" + description: "Don't create metadata before the device is bonded" + bug: "387523991" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/pbapclient.aconfig b/flags/pbapclient.aconfig index dbbbb7773b..2464557d58 100644 --- a/flags/pbapclient.aconfig +++ b/flags/pbapclient.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "pbap_client_storage_refactor" diff --git a/flags/ranging.aconfig b/flags/ranging.aconfig index 6b75003163..7851d5ff82 100644 --- a/flags/ranging.aconfig +++ b/flags/ranging.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "channel_sounding" diff --git a/flags/rfcomm.aconfig b/flags/rfcomm.aconfig index df53931078..a5d1ec94ce 100644 --- a/flags/rfcomm.aconfig +++ b/flags/rfcomm.aconfig @@ -1,12 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" - -flag { - name: "rfcomm_always_use_mitm" - namespace: "bluetooth" - description: "Use MITM initially to avoid abrupt peer disconnection b/312840315" - bug: "316824288" -} +container: "com.android.bt" flag { name: "rfcomm_prevent_unnecessary_collisions" diff --git a/flags/rnr.aconfig b/flags/rnr.aconfig index 6b19a5f77b..425db568d6 100644 --- a/flags/rnr.aconfig +++ b/flags/rnr.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "rnr_store_device_type" diff --git a/flags/sco.aconfig b/flags/sco.aconfig index 26379f4ea1..51c6e14e24 100644 --- a/flags/sco.aconfig +++ b/flags/sco.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "fix_sco_command_status_handling" diff --git a/flags/sdp.aconfig b/flags/sdp.aconfig index a20adb914a..418fa04663 100644 --- a/flags/sdp.aconfig +++ b/flags/sdp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "stack_sdp_detect_nil_property_type" diff --git a/flags/security.aconfig b/flags/security.aconfig index 2bb69eac95..ddfd78611c 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "key_missing_classic_device" @@ -36,10 +36,10 @@ flag { } flag { - name: "le_enc_on_reconnection" + name: "le_enc_on_reconnect" namespace: "bluetooth" description: "Encrypt LE link on reconnection with bonded devices" - bug: "356201480" + bug: "388864535" metadata { purpose: PURPOSE_BUGFIX } diff --git a/flags/service_discovery.aconfig b/flags/service_discovery.aconfig index f5569086b9..00c0741ff3 100644 --- a/flags/service_discovery.aconfig +++ b/flags/service_discovery.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "prevent_duplicate_uuid_intent" diff --git a/flags/sockets.aconfig b/flags/sockets.aconfig index 688d27323c..ded22e3da0 100644 --- a/flags/sockets.aconfig +++ b/flags/sockets.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "unix_file_socket_creation_failure" diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig index fba0792eca..65caf1e60c 100644 --- a/flags/system_service.aconfig +++ b/flags/system_service.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "enforce_resolve_system_service_behavior" diff --git a/flags/vcp.aconfig b/flags/vcp.aconfig index 2c7e4983ea..12e55de6ba 100644 --- a/flags/vcp.aconfig +++ b/flags/vcp.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "vcp_mute_unmute" diff --git a/flags/vsc.aconfig b/flags/vsc.aconfig index bd67729689..af4f375849 100644 --- a/flags/vsc.aconfig +++ b/flags/vsc.aconfig @@ -1,5 +1,5 @@ package: "com.android.bluetooth.flags" -container: "com.android.btservices" +container: "com.android.bt" flag { name: "hci_vendor_specific_extension" diff --git a/framework/Android.bp b/framework/Android.bp index 6e5dafc3e1..cd09db00e6 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -82,9 +82,7 @@ java_sdk_library { ":__subpackages__", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], permitted_packages: [ "android.bluetooth", diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index a6bcc53007..cfa9c8dad4 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -514,9 +514,9 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]); - method @FlaggedApi("com.android.bluetooth.flags.allow_switching_hid_and_hogp") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getPreferredTransport(@NonNull android.bluetooth.BluetoothDevice); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getPreferredTransport(@NonNull android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - method @FlaggedApi("com.android.bluetooth.flags.allow_switching_hid_and_hogp") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPreferredTransport(@NonNull android.bluetooth.BluetoothDevice, int); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPreferredTransport(@NonNull android.bluetooth.BluetoothDevice, int); field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED"; } diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index fad88d4b5e..08f880e04a 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -4203,6 +4203,46 @@ public final class BluetoothAdapter { return null; } + /** + * Return a binder to BluetoothAdvertise + * + * @hide + */ + @RequiresNoPermission + public @Nullable IBluetoothAdvertise getBluetoothAdvertise() { + mServiceLock.readLock().lock(); + try { + if (mService != null) { + return IBluetoothAdvertise.Stub.asInterface(mService.getBluetoothAdvertise()); + } + } catch (RemoteException e) { + logRemoteException(TAG, e); + } finally { + mServiceLock.readLock().unlock(); + } + return null; + } + + /** + * Return a binder to DistanceMeasurement + * + * @hide + */ + @RequiresNoPermission + public @Nullable IDistanceMeasurement getDistanceMeasurement() { + mServiceLock.readLock().lock(); + try { + if (mService != null) { + return IDistanceMeasurement.Stub.asInterface(mService.getDistanceMeasurement()); + } + } catch (RemoteException e) { + logRemoteException(TAG, e); + } finally { + mServiceLock.readLock().unlock(); + } + return null; + } + /** Return a binder to a Profile service */ private @Nullable IBinder getProfile(int profile) { mServiceLock.readLock().lock(); @@ -5830,8 +5870,8 @@ public final class BluetoothAdapter { * Register an {@link BluetoothHciVendorCallback} to listen for HCI vendor responses and events * * @param eventCodeSet Set of vendor-specific event codes to listen for updates. Each - * vendor-specific event code must be in the range 0x00 to 0x4f or 0x60 to 0xff. - * The inclusive range 0x50-0x5f is reserved by the system. + * vendor-specific event code must be in the range 0x00 to 0x4f or 0x60 to 0xff. The + * inclusive range 0x52-0x5f is reserved by the system. * @param executor an {@link Executor} to execute given callback * @param callback user implementation of the {@link BluetoothHciVendorCallback} * @throws IllegalArgumentException if the callback is already registered, or event codes not in @@ -5851,7 +5891,7 @@ public final class BluetoothAdapter { requireNonNull(executor); requireNonNull(callback); if (eventCodeSet.stream() - .anyMatch((n) -> (n < 0) || (n >= 0x50 && n < 0x60) || (n > 0xff))) { + .anyMatch((n) -> (n < 0) || (n >= 0x52 && n < 0x60) || (n > 0xff))) { throw new IllegalArgumentException("Event code not in valid range"); } diff --git a/framework/java/android/bluetooth/BluetoothHidHost.java b/framework/java/android/bluetooth/BluetoothHidHost.java index b9d3d0f158..b1e4de56a0 100644 --- a/framework/java/android/bluetooth/BluetoothHidHost.java +++ b/framework/java/android/bluetooth/BluetoothHidHost.java @@ -465,7 +465,6 @@ public final class BluetoothHidHost implements BluetoothProfile { * @throws IllegalArgumentException if the {@code device} invalid. * @hide */ - @FlaggedApi(Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission( @@ -569,7 +568,6 @@ public final class BluetoothHidHost implements BluetoothProfile { * @throws IllegalArgumentException if the {@code device} invalid. * @hide */ - @FlaggedApi(Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP) @SystemApi @RequiresBluetoothConnectPermission @RequiresPermission( diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java index bfaca06612..2e58a23c06 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java @@ -547,7 +547,9 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable { mAudioConfigQuality = original.getAudioConfigQuality(); mRssi = original.getRssi(); mPublicBroadcastMetadata = original.getPublicBroadcastMetadata(); - mSubgroups = original.getSubgroups(); + for (BluetoothLeBroadcastSubgroup subgroup : original.getSubgroups()) { + mSubgroups.add(new BluetoothLeBroadcastSubgroup.Builder(subgroup).build()); + } } /** diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java index e2b654c830..b53a33bcfa 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java @@ -229,7 +229,9 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable { mCodecId = original.getCodecId(); mCodecSpecificConfig = original.getCodecSpecificConfig(); mContentMetadata = original.getContentMetadata(); - mChannels = original.getChannels(); + for (BluetoothLeBroadcastChannel channel : original.getChannels()) { + mChannels.add(new BluetoothLeBroadcastChannel.Builder(channel).build()); + } } /** diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java index d33542e6d6..97bdf595a0 100644 --- a/framework/java/android/bluetooth/BluetoothSocket.java +++ b/framework/java/android/bluetooth/BluetoothSocket.java @@ -994,7 +994,7 @@ public final class BluetoothSocket implements Closeable { ret = mSocketIS.read(b, offset, length); } if (ret < 0) { - return -1; + throw new IOException("bt socket closed, read return: " + ret); } if (VDBG) Log.d(TAG, "read out: " + mSocketIS + " ret: " + ret); return ret; diff --git a/framework/java/android/bluetooth/le/AdvertisingSet.java b/framework/java/android/bluetooth/le/AdvertisingSet.java index 8632fcf671..5b3299b120 100644 --- a/framework/java/android/bluetooth/le/AdvertisingSet.java +++ b/framework/java/android/bluetooth/le/AdvertisingSet.java @@ -25,7 +25,7 @@ import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.bluetooth.BluetoothAdapter; -import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothAdvertise; import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission; import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission; import android.content.AttributionSource; @@ -43,18 +43,18 @@ import android.util.Log; public final class AdvertisingSet { private static final String TAG = "AdvertisingSet"; - private final IBluetoothGatt mGatt; + private final IBluetoothAdvertise mAdvertise; private int mAdvertiserId; private AttributionSource mAttributionSource; AdvertisingSet( - IBluetoothGatt gatt, + IBluetoothAdvertise advertise, int advertiserId, BluetoothAdapter bluetoothAdapter, AttributionSource attributionSource) { mAdvertiserId = advertiserId; mAttributionSource = attributionSource; - mGatt = requireNonNull(gatt, "Bluetooth gatt cannot be null"); + mAdvertise = requireNonNull(advertise, "Bluetooth advertise cannot be null"); } /* package */ void setAdvertiserId(int advertiserId) { @@ -77,7 +77,7 @@ public final class AdvertisingSet { @RequiresPermission(BLUETOOTH_ADVERTISE) public void enableAdvertising(boolean enable, int duration, int maxExtendedAdvertisingEvents) { try { - mGatt.enableAdvertisingSet( + mAdvertise.enableAdvertisingSet( mAdvertiserId, enable, duration, @@ -105,7 +105,7 @@ public final class AdvertisingSet { @RequiresPermission(BLUETOOTH_ADVERTISE) public void setAdvertisingData(AdvertiseData advertiseData) { try { - mGatt.setAdvertisingData(mAdvertiserId, advertiseData, mAttributionSource); + mAdvertise.setAdvertisingData(mAdvertiserId, advertiseData, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -125,7 +125,7 @@ public final class AdvertisingSet { @RequiresPermission(BLUETOOTH_ADVERTISE) public void setScanResponseData(AdvertiseData scanResponse) { try { - mGatt.setScanResponseData(mAdvertiserId, scanResponse, mAttributionSource); + mAdvertise.setScanResponseData(mAdvertiserId, scanResponse, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -149,7 +149,7 @@ public final class AdvertisingSet { conditional = true) public void setAdvertisingParameters(AdvertisingSetParameters parameters) { try { - mGatt.setAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource); + mAdvertise.setAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -165,7 +165,8 @@ public final class AdvertisingSet { @RequiresPermission(BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) { try { - mGatt.setPeriodicAdvertisingParameters(mAdvertiserId, parameters, mAttributionSource); + mAdvertise.setPeriodicAdvertisingParameters( + mAdvertiserId, parameters, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -186,7 +187,7 @@ public final class AdvertisingSet { @RequiresPermission(BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingData(AdvertiseData periodicData) { try { - mGatt.setPeriodicAdvertisingData(mAdvertiserId, periodicData, mAttributionSource); + mAdvertise.setPeriodicAdvertisingData(mAdvertiserId, periodicData, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -203,7 +204,7 @@ public final class AdvertisingSet { @RequiresPermission(BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingEnabled(boolean enable) { try { - mGatt.setPeriodicAdvertisingEnable(mAdvertiserId, enable, mAttributionSource); + mAdvertise.setPeriodicAdvertisingEnable(mAdvertiserId, enable, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } @@ -223,7 +224,7 @@ public final class AdvertisingSet { }) public void getOwnAddress() { try { - mGatt.getOwnAddress(mAdvertiserId, mAttributionSource); + mAdvertise.getOwnAddress(mAdvertiserId, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "remote exception - ", e); } diff --git a/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 057053e817..e43838f8be 100644 --- a/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/framework/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -29,7 +29,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGattServer; import android.bluetooth.BluetoothUuid; -import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothAdvertise; import android.bluetooth.annotations.RequiresBluetoothAdvertisePermission; import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission; import android.content.AttributionSource; @@ -610,10 +610,10 @@ public final class BluetoothLeAdvertiser { throw new IllegalArgumentException("duration out of range: " + duration); } - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); + IBluetoothAdvertise advertise = mBluetoothAdapter.getBluetoothAdvertise(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + if (advertise == null) { + Log.e(TAG, "Bluetooth Advertise is null"); postStartSetFailure( handler, callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); return; @@ -626,7 +626,7 @@ public final class BluetoothLeAdvertiser { } try { - gatt.startAdvertisingSet( + advertise.startAdvertisingSet( parameters, advertiseData, scanResponse, @@ -665,13 +665,13 @@ public final class BluetoothLeAdvertiser { return; } - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + IBluetoothAdvertise advertise = mBluetoothAdapter.getBluetoothAdvertise(); + if (advertise == null) { + Log.e(TAG, "Bluetooth Advertise is null"); return; } try { - gatt.stopAdvertisingSet(wrapped, mAttributionSource); + advertise.stopAdvertisingSet(wrapped, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "Failed to stop advertising - ", e); } @@ -789,7 +789,7 @@ public final class BluetoothLeAdvertiser { return new IAdvertisingSetCallback.Stub() { @Override public void onAdvertisingSetStarted( - IBinder gattBinder, int advertiserId, int txPower, int status) { + IBinder advertiseBinder, int advertiserId, int txPower, int status) { handler.post( () -> { if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) { @@ -800,7 +800,7 @@ public final class BluetoothLeAdvertiser { AdvertisingSet advertisingSet = new AdvertisingSet( - IBluetoothGatt.Stub.asInterface(gattBinder), + IBluetoothAdvertise.Stub.asInterface(advertiseBinder), advertiserId, mBluetoothAdapter, mAttributionSource); diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementManager.java b/framework/java/android/bluetooth/le/DistanceMeasurementManager.java index 1760bc0bf1..b68d3556e4 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementManager.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementManager.java @@ -27,7 +27,7 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IDistanceMeasurement; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.le.ChannelSoundingParams.CsSecurityLevel; import android.content.AttributionSource; @@ -94,12 +94,12 @@ public final class DistanceMeasurementManager { public @NonNull List<DistanceMeasurementMethod> getSupportedMethods() { final List<DistanceMeasurementMethod> supportedMethods = new ArrayList<>(); try { - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + IDistanceMeasurement distanceMeasurement = mBluetoothAdapter.getDistanceMeasurement(); + if (distanceMeasurement == null) { + Log.e(TAG, "Distance Measurement is null"); return supportedMethods; } - return gatt.getSupportedDistanceMeasurementMethods(mAttributionSource); + return distanceMeasurement.getSupportedDistanceMeasurementMethods(mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "Failed to get supported methods - ", e); } @@ -137,14 +137,19 @@ public final class DistanceMeasurementManager { Objects.requireNonNull(executor, "executor is null"); Objects.requireNonNull(callback, "callback is null"); try { - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + IDistanceMeasurement distanceMeasurement = mBluetoothAdapter.getDistanceMeasurement(); + if (distanceMeasurement == null) { + Log.e(TAG, "Distance Measurement is null"); return null; } DistanceMeasurementSession session = new DistanceMeasurementSession( - gatt, mUuid, params, executor, mAttributionSource, callback); + distanceMeasurement, + mUuid, + params, + executor, + mAttributionSource, + callback); CancellationSignal cancellationSignal = new CancellationSignal(); cancellationSignal.setOnCancelListener(() -> session.stopSession()); @@ -154,7 +159,8 @@ public final class DistanceMeasurementManager { } mSessionMap.put(params.getDevice(), session); - gatt.startDistanceMeasurement(mUuid, params, mCallbackWrapper, mAttributionSource); + distanceMeasurement.startDistanceMeasurement( + mUuid, params, mCallbackWrapper, mAttributionSource); return cancellationSignal; } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); @@ -185,12 +191,12 @@ public final class DistanceMeasurementManager { Objects.requireNonNull(remoteDevice, "remote device is null"); final int defaultValue = ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN; try { - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + IDistanceMeasurement distanceMeasurement = mBluetoothAdapter.getDistanceMeasurement(); + if (distanceMeasurement == null) { + Log.e(TAG, "Distance Measurement is null"); return defaultValue; } - return gatt.getChannelSoundingMaxSupportedSecurityLevel( + return distanceMeasurement.getChannelSoundingMaxSupportedSecurityLevel( remoteDevice, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "Failed to get supported security Level - ", e); @@ -217,12 +223,13 @@ public final class DistanceMeasurementManager { public @CsSecurityLevel int getLocalChannelSoundingMaxSupportedSecurityLevel() { final int defaultValue = ChannelSoundingParams.CS_SECURITY_LEVEL_UNKNOWN; try { - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + IDistanceMeasurement distanceMeasurement = mBluetoothAdapter.getDistanceMeasurement(); + if (distanceMeasurement == null) { + Log.e(TAG, "Distance Measurement is null"); return defaultValue; } - return gatt.getLocalChannelSoundingMaxSupportedSecurityLevel(mAttributionSource); + return distanceMeasurement.getLocalChannelSoundingMaxSupportedSecurityLevel( + mAttributionSource); } catch (RemoteException e) { Log.e(TAG, "Failed to get supported security Level - ", e); } @@ -247,12 +254,14 @@ public final class DistanceMeasurementManager { @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @NonNull Set<@CsSecurityLevel Integer> getChannelSoundingSupportedSecurityLevels() { try { - IBluetoothGatt gatt = mBluetoothAdapter.getBluetoothGatt(); - if (gatt == null) { - Log.e(TAG, "Bluetooth GATT is null"); + IDistanceMeasurement distanceMeasurement = mBluetoothAdapter.getDistanceMeasurement(); + if (distanceMeasurement == null) { + Log.e(TAG, "Distance Measurement is null"); return Collections.emptySet(); } - return Arrays.stream(gatt.getChannelSoundingSupportedSecurityLevels(mAttributionSource)) + return Arrays.stream( + distanceMeasurement.getChannelSoundingSupportedSecurityLevels( + mAttributionSource)) .boxed() .collect(Collectors.toUnmodifiableSet()); } catch (RemoteException e) { diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java index a36887ba9b..d0c9547967 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java @@ -28,7 +28,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothStatusCodes; -import android.bluetooth.IBluetoothGatt; +import android.bluetooth.IDistanceMeasurement; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.content.AttributionSource; import android.os.ParcelUuid; @@ -60,7 +60,7 @@ import java.util.concurrent.Executor; public final class DistanceMeasurementSession { private static final String TAG = "DistanceMeasurementSession"; - private final IBluetoothGatt mGatt; + private final IDistanceMeasurement mDistanceMeasurement; private final ParcelUuid mUuid; private final DistanceMeasurementParams mDistanceMeasurementParams; private final Executor mExecutor; @@ -79,13 +79,13 @@ public final class DistanceMeasurementSession { /** @hide */ public DistanceMeasurementSession( - IBluetoothGatt gatt, + IDistanceMeasurement distanceMeasurement, ParcelUuid uuid, DistanceMeasurementParams params, Executor executor, AttributionSource attributionSource, Callback callback) { - mGatt = requireNonNull(gatt); + mDistanceMeasurement = requireNonNull(distanceMeasurement); mDistanceMeasurementParams = requireNonNull(params); mExecutor = requireNonNull(executor); mCallback = requireNonNull(callback); @@ -104,7 +104,7 @@ public final class DistanceMeasurementSession { @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public @StopSessionReturnValues int stopSession() { try { - return mGatt.stopDistanceMeasurement( + return mDistanceMeasurement.stopDistanceMeasurement( mUuid, mDistanceMeasurementParams.getDevice(), mDistanceMeasurementParams.getMethodId(), diff --git a/framework/tests/bumble/AndroidPhyTest.xml b/framework/tests/bumble/AndroidPhyTest.xml index 4e5eb02e5f..b762ec7480 100644 --- a/framework/tests/bumble/AndroidPhyTest.xml +++ b/framework/tests/bumble/AndroidPhyTest.xml @@ -47,8 +47,8 @@ <!-- Only run if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> <!-- Collect Bluetooth snoop logs for each test run --> diff --git a/framework/tests/bumble/AndroidTest.xml b/framework/tests/bumble/AndroidTest.xml index 4855fec134..04aedce061 100644 --- a/framework/tests/bumble/AndroidTest.xml +++ b/framework/tests/bumble/AndroidTest.xml @@ -48,8 +48,8 @@ <!-- Only run if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> <!-- Collect Bluetooth snoop logs for each test run --> diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java index f8324d9592..faf79ef23f 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHeadTrackerTest.java @@ -55,7 +55,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.ParcelUuid; -import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Log; @@ -63,7 +62,6 @@ import android.util.Log; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.bluetooth.flags.Flags; import com.android.compatibility.common.util.AdoptShellPermissionsRule; import org.hamcrest.CustomTypeSafeMatcher; @@ -292,9 +290,7 @@ public class HidHeadTrackerTest { */ @SuppressLint("MissingPermission") @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void connectWithoutHidServiceTest() { - registerIntentActions( BluetoothDevice.ACTION_ACL_CONNECTED, BluetoothDevice.ACTION_ACL_DISCONNECTED, @@ -385,9 +381,7 @@ public class HidHeadTrackerTest { */ @SuppressLint("MissingPermission") @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void connectWithHidServiceTest() { - registerIntentActions( BluetoothDevice.ACTION_ACL_CONNECTED, BluetoothDevice.ACTION_UUID, diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java index 167e583d7d..2a8d9a2787 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java @@ -57,7 +57,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.ParcelUuid; import android.os.Parcelable; -import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.util.Log; @@ -392,7 +391,6 @@ public class HidHostDualModeTest { * </ol> */ @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void setPreferredTransportTest() { // BR/EDR transport mHidService.setPreferredTransport(mDevice, TRANSPORT_BREDR); @@ -410,7 +408,6 @@ public class HidHostDualModeTest { * </ol> */ @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hogpGetReportTest() throws Exception { // Keyboard report mReportData = new byte[0]; @@ -444,7 +441,6 @@ public class HidHostDualModeTest { * </ol> */ @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hogpGetProtocolModeTest() { mHidService.getProtocolMode(mDevice); verifyIntentReceived( @@ -463,7 +459,6 @@ public class HidHostDualModeTest { * </ol> */ @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hogpSetProtocolModeTest() throws Exception { mHidService.setProtocolMode(mDevice, BluetoothHidHost.PROTOCOL_BOOT_MODE); // Must cast ERROR_RSP_SUCCESS, otherwise, it won't match with the int extra @@ -482,7 +477,6 @@ public class HidHostDualModeTest { * </ol> */ @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hogpSetReportTest() throws Exception { // Keyboard report mHidService.setReport(mDevice, BluetoothHidHost.REPORT_TYPE_INPUT, "010203040506070809"); @@ -509,7 +503,6 @@ public class HidHostDualModeTest { * </ol> */ @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hogpVirtualUnplugFromHidHostTest() throws Exception { mHidService.virtualUnplug(mDevice); verifyIntentReceived( diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java index 1cb9e083fb..c7a3d48c8b 100644 --- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java +++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java @@ -16,7 +16,6 @@ package android.bluetooth.hid; -import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; import static android.bluetooth.BluetoothDevice.TRANSPORT_BREDR; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; @@ -323,15 +322,9 @@ public class HidHostTest { mDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN)) .isTrue(); } - if (Flags.allowSwitchingHidAndHogp()) { - verifyConnectionState(mDevice, equalTo(TRANSPORT_BREDR), equalTo(STATE_CONNECTING)); - verifyConnectionState(mDevice, equalTo(TRANSPORT_BREDR), equalTo(STATE_CONNECTED)); - assertThat(mHidService.getPreferredTransport(mDevice)).isEqualTo(TRANSPORT_BREDR); - } else { - // Without allowSwitchingHidAndHogp, transport will be AUTO - verifyConnectionState(mDevice, equalTo(TRANSPORT_AUTO), equalTo(STATE_CONNECTING)); - verifyConnectionState(mDevice, equalTo(TRANSPORT_AUTO), equalTo(STATE_CONNECTED)); - } + verifyConnectionState(mDevice, equalTo(TRANSPORT_BREDR), equalTo(STATE_CONNECTING)); + verifyConnectionState(mDevice, equalTo(TRANSPORT_BREDR), equalTo(STATE_CONNECTED)); + assertThat(mHidService.getPreferredTransport(mDevice)).isEqualTo(TRANSPORT_BREDR); } @SuppressLint("MissingPermission") @@ -381,7 +374,6 @@ public class HidHostTest { */ @SuppressLint("MissingPermission") @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hidReconnectionWhenConnectionPolicyChangeTest() throws Exception { assertThat(mHidService.getConnectionPolicy(mDevice)) @@ -437,7 +429,6 @@ public class HidHostTest { */ @SuppressLint("MissingPermission") @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hidReconnectionAfterBTrestartWithConnectionPolicyAllowedTest() throws Exception { assertThat(mHidService.getConnectionPolicy(mDevice)) @@ -462,7 +453,6 @@ public class HidHostTest { */ @SuppressLint("MissingPermission") @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hidReconnectionAfterBTrestartWithConnectionPolicyiDisallowedTest() throws Exception { @@ -490,7 +480,6 @@ public class HidHostTest { */ @SuppressLint("MissingPermission") @Test - @RequiresFlagsEnabled({Flags.FLAG_ALLOW_SWITCHING_HID_AND_HOGP}) public void hidReconnectionAfterDeviceRemovedTest() throws Exception { assertThat(mHidService.getConnectionPolicy(mDevice)) @@ -731,62 +720,34 @@ public class HidHostTest { private void verifyConnectionState( BluetoothDevice device, Matcher<Integer> transport, Matcher<Integer> state) { - if (Flags.allowSwitchingHidAndHogp()) { - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, device), - hasExtra(BluetoothDevice.EXTRA_TRANSPORT, transport), - hasExtra(BluetoothProfile.EXTRA_STATE, state)); - } else { - // skip transport verification - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, device), - hasExtra(BluetoothProfile.EXTRA_STATE, state)); - } + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, transport), + hasExtra(BluetoothProfile.EXTRA_STATE, state)); } private void verifyIncomingProfileConnectionState() { // for incoming connection, connection state transit // from STATE_ACCEPTING -->STATE_CONNECTED - if (Flags.allowSwitchingHidAndHogp()) { - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), - hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTED)); - } else { - // skip transport verification - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTED)); - } + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_CONNECTED)); } private void verifyProfileDisconnectionState() { - if (Flags.allowSwitchingHidAndHogp()) { - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), - hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTING)); - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), - hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTED)); - } else { - // skip transport verification - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTING)); - verifyIntentReceived( - hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), - hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), - hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTED)); - } + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTING)); + verifyIntentReceived( + hasAction(BluetoothHidHost.ACTION_CONNECTION_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, TRANSPORT_BREDR), + hasExtra(BluetoothProfile.EXTRA_STATE, STATE_DISCONNECTED)); } private void reconnectionFromRemoteAndVerifyDisconnectedState() throws Exception { diff --git a/framework/tests/unit/AndroidTest.xml b/framework/tests/unit/AndroidTest.xml index f3e71f3b75..2f675b852e 100644 --- a/framework/tests/unit/AndroidTest.xml +++ b/framework/tests/unit/AndroidTest.xml @@ -39,7 +39,7 @@ <!-- Only run FrameworkBluetoothTests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/framework/tests/util/src/android/bluetooth/cts/TestUtils.java b/framework/tests/util/src/android/bluetooth/cts/TestUtils.java index 4d3a39fe60..dd1e777164 100644 --- a/framework/tests/util/src/android/bluetooth/cts/TestUtils.java +++ b/framework/tests/util/src/android/bluetooth/cts/TestUtils.java @@ -30,8 +30,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.test.platform.app.InstrumentationRegistry; -import com.google.errorprone.annotations.InlineMe; - public class TestUtils extends android.bluetooth.test_utils.TestUtils { /** * Get the current enabled status of a given profile. @@ -161,23 +159,6 @@ public class TestUtils extends android.bluetooth.test_utils.TestUtils { } /** - * Utility method to assert two byte arrays are equal. - * - * @param expected expected value - * @param actual actual value - * @deprecated Please use {@link com.google.common.truth.Truth}, - * "assertThat(actual).isEqualTo(expected)". Keeping it here since some tests are still - * using it. - */ - @Deprecated - @InlineMe( - replacement = "assertThat(actual).isEqualTo(expected)", - staticImports = "com.google.common.truth.Truth.assertThat") - public static void assertArrayEquals(byte[] expected, byte[] actual) { - assertThat(actual).isEqualTo(expected); - } - - /** * DANGER: Put the current thread to sleep. Please only use this when it is ok to block the * current thread. * diff --git a/service/Android.bp b/service/Android.bp index 5fbf29b91c..63fd7b8faa 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -88,12 +88,11 @@ java_library { sdk_version: "system_server_current", min_sdk_version: "Tiramisu", - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], visibility: [":__subpackages__"], } // Apply jarjaring before using library in the apex -// TODO b/383863941 delete and merge with service-bluetooth-new java_library { name: "service-bluetooth", static_libs: ["service-bluetooth-pre-jarjar"], @@ -113,30 +112,6 @@ java_library { sdk_version: "system_server_current", min_sdk_version: "Tiramisu", - apex_available: ["com.android.btservices"], - visibility: ["//packages/modules/Bluetooth/apex"], -} - -// Apply jarjaring before using library in the apex -java_library { - name: "service-bluetooth-new", - static_libs: ["service-bluetooth-pre-jarjar"], - installable: true, - - jarjar_rules: ":bluetooth-jarjar-rules", - - optimize: { - enabled: true, - shrink: true, - proguard_flags_files: ["proguard.flags"], - }, - - libs: [ - "framework-bluetooth.impl", - ], - - sdk_version: "system_server_current", - min_sdk_version: "Tiramisu", apex_available: ["com.android.bt"], visibility: ["//packages/modules/Bluetooth/apex"], } @@ -153,7 +128,7 @@ java_library { sdk_version: "system_server_current", min_sdk_version: "Tiramisu", - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], } java_library { @@ -172,7 +147,7 @@ java_library { sdk_version: "system_current", min_sdk_version: "Tiramisu", - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], } android_robolectric_test { @@ -226,7 +201,6 @@ android_robolectric_test { ], sdk_version: "test_current", - upstream: true, test_suites: ["general-tests"], strict_mode: false, } diff --git a/service/aidl/Android.bp b/service/aidl/Android.bp index d7adba534e..14980c7520 100644 --- a/service/aidl/Android.bp +++ b/service/aidl/Android.bp @@ -17,6 +17,6 @@ java_library { libs: ["framework-annotations-lib"], sdk_version: "module_current", min_sdk_version: "Tiramisu", - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], visibility: ["//packages/modules/Bluetooth:__subpackages__"], } diff --git a/service/change-ids/Android.bp b/service/change-ids/Android.bp index 3544d6b1e2..b717d09e36 100644 --- a/service/change-ids/Android.bp +++ b/service/change-ids/Android.bp @@ -22,7 +22,7 @@ java_library { libs: ["app-compat-annotations"], sdk_version: "system_server_current", min_sdk_version: "Tiramisu", - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], visibility: ["//packages/modules/Bluetooth/service:__subpackages__"], } diff --git a/service/tests/AndroidTest.xml b/service/tests/AndroidTest.xml index 4e1be42419..c759326927 100644 --- a/service/tests/AndroidTest.xml +++ b/service/tests/AndroidTest.xml @@ -28,8 +28,7 @@ <option name="test-suite-tag" value="apct" /> <option name="test-tag" value="ServiceBluetoothTests" /> - <option name="config-descriptor:metadata" key="mainline-param" - value="com.google.android.btservices.apex" /> + <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.bt.apex" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.server.bluetooth.test" /> <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> @@ -39,7 +38,7 @@ <!-- Only run FrameworkBluetoothTests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/sysprop/Android.bp b/sysprop/Android.bp index e9d820b2f1..241e8711f7 100644 --- a/sysprop/Android.bp +++ b/sysprop/Android.bp @@ -20,7 +20,7 @@ sysprop_library { cpp: { min_sdk_version: "Tiramisu", }, - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], } cc_library_static { @@ -30,6 +30,6 @@ cc_library_static { export_include_dirs: ["exported_include"], export_static_lib_headers: ["libcom.android.sysprop.bluetooth"], visibility: ["//packages/modules/Bluetooth/system:__subpackages__"], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } diff --git a/system/Android.bp b/system/Android.bp index 1ecb8b81d7..9d47e06596 100644 --- a/system/Android.bp +++ b/system/Android.bp @@ -28,7 +28,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "30", } diff --git a/system/audio/Android.bp b/system/audio/Android.bp index 481182dc5f..98677c206a 100644 --- a/system/audio/Android.bp +++ b/system/audio/Android.bp @@ -41,9 +41,7 @@ cc_library_static { ], host_supported: true, min_sdk_version: "33", - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], } cc_library_host_shared { diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index 363627401f..cc33db9a51 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -79,9 +79,7 @@ cc_library_static { cflags: [ "-Wthread-safety", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], } diff --git a/system/audio_hal_interface/a2dp_encoding.h b/system/audio_hal_interface/a2dp_encoding.h index 2f31b281bf..30e4a34e34 100644 --- a/system/audio_hal_interface/a2dp_encoding.h +++ b/system/audio_hal_interface/a2dp_encoding.h @@ -38,6 +38,7 @@ enum class Status { UNSUPPORTED_CODEC_CONFIGURATION, FAILURE, PENDING, + RECONFIGURATION, }; /// Loosely copied after the definition from the Bluetooth Audio interface: diff --git a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h index a45ff946f2..bf687e75c9 100644 --- a/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h +++ b/system/audio_hal_interface/aidl/a2dp/client_interface_aidl.h @@ -72,6 +72,8 @@ inline BluetoothAudioStatus StatusToHalStatus(Status ack) { return BluetoothAudioStatus::SUCCESS; case Status::UNSUPPORTED_CODEC_CONFIGURATION: return BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION; + case Status::RECONFIGURATION: + return BluetoothAudioStatus::RECONFIGURATION; case Status::PENDING: case Status::FAILURE: default: diff --git a/system/audio_hal_interface/aidl/le_audio_utils.cc b/system/audio_hal_interface/aidl/le_audio_utils.cc index 1a6a4f4e4c..6cd96a423a 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils.cc +++ b/system/audio_hal_interface/aidl/le_audio_utils.cc @@ -18,14 +18,23 @@ #include <com_android_bluetooth_flags.h> +#include <iomanip> #include <optional> +#include <sstream> +#include "aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h" +#include "bta/le_audio/gmap_server.h" +#include "bta/le_audio/le_audio_types.h" #include "hardware/bt_le_audio.h" namespace bluetooth { namespace audio { namespace aidl { +using ::aidl::android::hardware::bluetooth::audio::CodecInfo; +using ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags; +using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory; + ::aidl::android::hardware::bluetooth::audio::CodecId GetAidlCodecIdFromStackFormat( const ::bluetooth::le_audio::types::LeAudioCodecId& codec_id) { ::aidl::android::hardware::bluetooth::audio::CodecId codec; @@ -507,6 +516,24 @@ static ::bluetooth::le_audio::set_configurations::AseConfiguration GetStackAseCo return config; } +static std::string StackTargetLatencyToString(uint8_t target_latency) { + switch (target_latency) { + case ::bluetooth::le_audio::types::kTargetLatencyUndefined: + return "TargetLatencyUndefined"; + case ::bluetooth::le_audio::types::kTargetLatencyLower: + return "LowLatency"; + case ::bluetooth::le_audio::types::kTargetLatencyBalancedLatencyReliability: + return "BalancedReliability"; + case ::bluetooth::le_audio::types::kTargetLatencyHigherReliability: + return "HighReliability"; + default: + std::stringstream str; + str << "TargetLatencyUnknown (" << std::hex << std::setw(2) << std::setfill('0') + << target_latency << ")"; + return str.str(); + } +} + static std::string GenerateNameForConfig( const ::bluetooth::le_audio::set_configurations::AudioSetConfiguration& config) { auto namegen = [](const std::vector<::bluetooth::le_audio::set_configurations::AseConfiguration>& @@ -550,7 +577,7 @@ static std::string GenerateNameForConfig( cfg_str << "_" << current_codec.GetDataIntervalUs() << "us"; } // QoS - cfg_str << "-TargetLatency_" << +current_config->qos.target_latency; + cfg_str << "-" << StackTargetLatencyToString(current_config->qos.target_latency); if (last_equal_config == configs.end()) { break; @@ -607,6 +634,18 @@ GetStackConfigSettingFromAidl( } } + if (aidl_ase_config.flags.has_value()) { + if (aidl_ase_config.flags->bitmask & + ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags:: + ALLOW_ASYMMETRIC_CONFIGURATIONS) { + log::debug("Asymmetric configuration support flag set."); + } + if (aidl_ase_config.flags->bitmask & + ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags::LOW_LATENCY) { + log::debug("Low latency support flag set."); + } + } + cig_config.name = GenerateNameForConfig(cig_config); return cig_config; } @@ -625,6 +664,87 @@ GetStackUnicastConfigurationFromAidlFormat( return stack_config; } +static bool isAsymmetricConfigurationSupported( + IBluetoothAudioProviderFactory::ProviderInfo const& provider_info) { + for (auto& codec_info : provider_info.codecInfos) { + if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio) { + return false; + } + + auto flags = codec_info.transport.get<CodecInfo::Transport::leAudio>().flags; + + if (!flags) { + continue; + } + + if (flags->bitmask & ConfigurationFlags::ALLOW_ASYMMETRIC_CONFIGURATIONS) { + return true; + } + } + + return false; +} + +static bool isLowLatencyConfigurationSupported( + IBluetoothAudioProviderFactory::ProviderInfo const& provider_info) { + for (auto& codec_info : provider_info.codecInfos) { + if (codec_info.transport.getTag() != CodecInfo::Transport::leAudio) { + return false; + } + + auto flags = codec_info.transport.get<CodecInfo::Transport::leAudio>().flags; + + if (!flags) { + continue; + } + + if (flags->bitmask & ConfigurationFlags::LOW_LATENCY) { + return true; + } + } + + return false; +} + +std::optional<bluetooth::le_audio::ProviderInfo> GetStackProviderInfoFromAidl( + std::optional<IBluetoothAudioProviderFactory::ProviderInfo> const& encoding_provider_info, + std::optional<IBluetoothAudioProviderFactory::ProviderInfo> const& decoding_provider_info) { + (void)encoding_provider_info; + (void)decoding_provider_info; + + if (!encoding_provider_info.has_value() && !decoding_provider_info.has_value()) { + log::error("Neither the encoding or decoding provider info are correct."); + return std::nullopt; + } + + std::optional<bluetooth::le_audio::ProviderInfo> result = bluetooth::le_audio::ProviderInfo(); + if (encoding_provider_info.has_value()) { + log::debug("Encoding: {}", encoding_provider_info->toString()); + if (isAsymmetricConfigurationSupported(encoding_provider_info.value())) { + result->allowAsymmetric = true; + } + + if (isLowLatencyConfigurationSupported(encoding_provider_info.value())) { + result->lowLatency = true; + } + } + + if (decoding_provider_info.has_value()) { + // Iterate and print for the debugging purpose + log::debug("Decoding: {}", decoding_provider_info->toString()); + if (isAsymmetricConfigurationSupported(decoding_provider_info.value())) { + result->allowAsymmetric = true; + } + + if (isLowLatencyConfigurationSupported(decoding_provider_info.value())) { + result->lowLatency = true; + } + } + + log::debug("Stack: {}", result->toString()); + return result; +} + ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioBroadcastConfigurationRequirement GetAidlLeAudioBroadcastConfigurationRequirementFromStackFormat( @@ -664,7 +784,8 @@ GetStackUnicastConfigurationFromAidlFormat( DeviceDirectionRequirements>>& sink_reqs, const std::optional<std::vector< ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements:: - DeviceDirectionRequirements>>& source_reqs) { + DeviceDirectionRequirements>>& source_reqs, + ::bluetooth::le_audio::CodecManager::Flags flags) { auto aidl_reqs = ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioConfigurationRequirement(); @@ -720,7 +841,19 @@ GetStackUnicastConfigurationFromAidlFormat( aidl_reqs.audioContext.bitmask = (uint32_t)context_type; // TODO(b/341935895): Add the feature flags mechanism in the stack - // aidl_reqs.flags + if (flags != ::bluetooth::le_audio::CodecManager::Flags::NONE) { + aidl_reqs.flags = + std::make_optional<::aidl::android::hardware::bluetooth::audio::ConfigurationFlags>(); + if (flags & ::bluetooth::le_audio::CodecManager::Flags::ALLOW_ASYMMETRIC) { + aidl_reqs.flags->bitmask |= ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags:: + ALLOW_ASYMMETRIC_CONFIGURATIONS; + } + + if (flags & ::bluetooth::le_audio::CodecManager::Flags::LOW_LATENCY) { + aidl_reqs.flags->bitmask |= + ::aidl::android::hardware::bluetooth::audio::ConfigurationFlags::LOW_LATENCY; + } + } return aidl_reqs; } diff --git a/system/audio_hal_interface/aidl/le_audio_utils.h b/system/audio_hal_interface/aidl/le_audio_utils.h index df9d2e044e..25efabdc28 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils.h +++ b/system/audio_hal_interface/aidl/le_audio_utils.h @@ -63,7 +63,8 @@ GetAidlLeAudioDeviceCapabilitiesFromStackFormat( DeviceDirectionRequirements>>& sink_reqs, const std::optional<std::vector< ::bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements:: - DeviceDirectionRequirements>>& source_reqs); + DeviceDirectionRequirements>>& source_reqs, + ::bluetooth::le_audio::CodecManager::Flags flags); ::bluetooth::le_audio::types::LeAudioLtvMap GetStackLeAudioLtvMapFromAidlFormat( const std::vector< ::aidl::android::hardware::bluetooth::audio::CodecSpecificConfigurationLtv>& @@ -94,6 +95,12 @@ GetStackUnicastConfigurationFromAidlFormat( const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioAseConfigurationSetting& config); +std::optional<bluetooth::le_audio::ProviderInfo> GetStackProviderInfoFromAidl( + std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory:: + ProviderInfo> const& encoding_provider_info, + std::optional<::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory:: + ProviderInfo> const& decoding_provider_info); + } // namespace aidl } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc b/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc index 98fee01e5b..669c4fb4b0 100644 --- a/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc +++ b/system/audio_hal_interface/aidl/le_audio_utils_unittest.cc @@ -919,8 +919,8 @@ TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFrom ASSERT_EQ(stack_config->confs.source.size(), 2ul); ASSERT_EQ(*stack_config, expected_stack_config); ASSERT_EQ(stack_config->name, - "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_7500us-TargetLatency_2-" - "2-1chan-SourceAse-CodecId_6_0_0-24000hz_80oct_7500us-TargetLatency_1"); + "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_7500us-BalancedReliability-" + "2-1chan-SourceAse-CodecId_6_0_0-24000hz_80oct_7500us-LowLatency"); } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFromAidlFormatMonoLoc) { @@ -935,8 +935,8 @@ TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackUnicastConfigurationFrom ASSERT_EQ(stack_config->confs.source.size(), 1ul); ASSERT_EQ(*stack_config, expected_stack_config); ASSERT_EQ(stack_config->name, - "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_7500us-TargetLatency_2-" - "1-1chan-SourceAse-CodecId_6_0_0-24000hz_80oct_7500us-TargetLatency_1"); + "AIDL-2-1chan-SinkAse-CodecId_6_0_0-48000hz_120oct_7500us-BalancedReliability-" + "1-1chan-SourceAse-CodecId_6_0_0-24000hz_80oct_7500us-LowLatency"); } TEST(BluetoothAudioClientInterfaceAidlTest, testGetStackBisConfigFromAidlFormat) { @@ -1007,8 +1007,10 @@ TEST(BluetoothAudioClientInterfaceAidlTest, aidl_req_l, aidl_req_r}; reference_aidl_requirements.sourceAseRequirement = reference_aidl_requirements.sinkAseRequirement; + ::bluetooth::le_audio::CodecManager::Flags flags = + ::bluetooth::le_audio::CodecManager::Flags::NONE; auto aidl_requirements = GetAidlLeAudioUnicastConfigurationRequirementsFromStackFormat( - stack_context, stack_sink_reqs, stack_source_reqs); + stack_context, stack_sink_reqs, stack_source_reqs, flags); ASSERT_EQ(aidl_requirements.audioContext, reference_aidl_requirements.audioContext); ASSERT_EQ(aidl_requirements.flags, reference_aidl_requirements.flags); diff --git a/system/audio_hal_interface/le_audio_software.cc b/system/audio_hal_interface/le_audio_software.cc index d58483e340..4d6cd88010 100644 --- a/system/audio_hal_interface/le_audio_software.cc +++ b/system/audio_hal_interface/le_audio_software.cc @@ -25,6 +25,7 @@ #include <vector> #include "aidl/android/hardware/bluetooth/audio/AudioContext.h" +#include "aidl/client_interface_aidl.h" #include "aidl/le_audio_software_aidl.h" #include "aidl/le_audio_utils.h" #include "bta/le_audio/codec_manager.h" @@ -36,10 +37,12 @@ namespace bluetooth { namespace audio { +using aidl::BluetoothAudioClientInterface; using aidl::GetAidlLeAudioBroadcastConfigurationRequirementFromStackFormat; using aidl::GetAidlLeAudioDeviceCapabilitiesFromStackFormat; using aidl::GetAidlLeAudioUnicastConfigurationRequirementsFromStackFormat; using aidl::GetStackBroadcastConfigurationFromAidlFormat; +using aidl::GetStackProviderInfoFromAidl; using aidl::GetStackUnicastConfigurationFromAidlFormat; namespace le_audio { @@ -53,6 +56,7 @@ using ::aidl::android::hardware::bluetooth::audio::AudioContext; using ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider; using ::aidl::android::hardware::bluetooth::audio::LatencyMode; using ::aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration; +using ::aidl::android::hardware::bluetooth::audio::SessionType; using ::bluetooth::le_audio::CodecManager; using ::bluetooth::le_audio::set_configurations::AudioSetConfiguration; @@ -329,7 +333,7 @@ LeAudioClientInterface::Sink::GetUnicastConfig( std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement> reqs; reqs.push_back(GetAidlLeAudioUnicastConfigurationRequirementsFromStackFormat( requirements.audio_context_type, requirements.sink_requirements, - requirements.source_requirements)); + requirements.source_requirements, requirements.flags)); log::debug("Making an AIDL call"); auto aidl_configs = get_aidl_client_interface(is_broadcaster_) @@ -830,6 +834,26 @@ void LeAudioClientInterface::SetAllowedDsaModes(DsaModes dsa_modes) { } } +std::optional<bluetooth::le_audio::ProviderInfo> LeAudioClientInterface::GetCodecConfigProviderInfo( + void) const { + if (HalVersionManager::GetHalTransport() != BluetoothAudioHalTransport::AIDL) { + log::error("Not using an AIDL HAL transport. Provider Info is not available."); + return std::nullopt; + } + + auto encoding_provider_info = BluetoothAudioClientInterface::GetProviderInfo( + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH, nullptr); + + auto decoding_provider_info = BluetoothAudioClientInterface::GetProviderInfo( + SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH, nullptr); + + if (!encoding_provider_info.has_value() && !decoding_provider_info.has_value()) { + log::info("LE Audio offload codec extensibility is enabled, but the provider info is empty"); + return std::nullopt; + } + + return GetStackProviderInfoFromAidl(encoding_provider_info, decoding_provider_info); +} } // namespace le_audio } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/le_audio_software.h b/system/audio_hal_interface/le_audio_software.h index 67d804753a..fbc6f4400f 100644 --- a/system/audio_hal_interface/le_audio_software.h +++ b/system/audio_hal_interface/le_audio_software.h @@ -178,6 +178,9 @@ public: // singleton. static LeAudioClientInterface* Get(); + // Get the Codec Configuration Provider info + std::optional<bluetooth::le_audio::ProviderInfo> GetCodecConfigProviderInfo(void) const; + private: static LeAudioClientInterface* interface; Sink* unicast_sink_ = nullptr; diff --git a/system/audio_hal_interface/le_audio_software_host.cc b/system/audio_hal_interface/le_audio_software_host.cc index 28f2592a6c..fba4c77716 100644 --- a/system/audio_hal_interface/le_audio_software_host.cc +++ b/system/audio_hal_interface/le_audio_software_host.cc @@ -570,6 +570,11 @@ LeAudioClientInterface* LeAudioClientInterface::Get() { void LeAudioClientInterface::SetAllowedDsaModes(DsaModes /*dsa_modes*/) { return; } +std::optional<bluetooth::le_audio::ProviderInfo> LeAudioClientInterface::GetCodecConfigProviderInfo( + void) const { + return std::nullopt; +} + } // namespace le_audio } // namespace audio } // namespace bluetooth diff --git a/system/audio_hal_interface/le_audio_software_unittest.cc b/system/audio_hal_interface/le_audio_software_unittest.cc index fdf03dd65c..21db531e07 100644 --- a/system/audio_hal_interface/le_audio_software_unittest.cc +++ b/system/audio_hal_interface/le_audio_software_unittest.cc @@ -130,6 +130,10 @@ public: IBluetoothAudioProvider::LeAudioDeviceCapabilities>>>&), (const ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider:: LeAudioBroadcastConfigurationRequirement&))); + MOCK_METHOD(std::optional<bluetooth::audio::aidl::IBluetoothAudioProviderFactory::ProviderInfo>, + GetProviderInfo, + ((bluetooth::audio::aidl::SessionType), + (std::shared_ptr<bluetooth::audio::aidl::IBluetoothAudioProviderFactory>))); static void SetInstance(MockBluetoothAudioClientInterfaceAidl* ptr) { instance_ptr = ptr; } @@ -416,6 +420,17 @@ std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabiliti return std::vector<AudioCapabilities>(0); } +std::optional<bluetooth::audio::aidl::IBluetoothAudioProviderFactory::ProviderInfo> +BluetoothAudioClientInterface::GetProviderInfo( + bluetooth::audio::aidl::SessionType session_type, + std::shared_ptr<bluetooth::audio::aidl::IBluetoothAudioProviderFactory> provider_factory) { + auto instance = MockBluetoothAudioClientInterfaceAidl::GetInstance(); + if (instance) { + return instance->GetProviderInfo(session_type, provider_factory); + } + return std::nullopt; +} + std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> BluetoothAudioClientInterface::GetLeAudioAseConfiguration( std::optional< diff --git a/system/audio_hearing_aid_hw/Android.bp b/system/audio_hearing_aid_hw/Android.bp index e8e83e86c8..afc160d599 100644 --- a/system/audio_hearing_aid_hw/Android.bp +++ b/system/audio_hearing_aid_hw/Android.bp @@ -27,9 +27,7 @@ cc_library { "src/audio_hearing_aid_hw.cc", "src/audio_hearing_aid_hw_utils.cc", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], shared_libs: [ "libbase", "liblog", diff --git a/system/bta/Android.bp b/system/bta/Android.bp index efa1d25fd1..63bd5f4e53 100644 --- a/system/bta/Android.bp +++ b/system/bta/Android.bp @@ -168,9 +168,7 @@ cc_library_static { ], }, }, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } @@ -225,9 +223,7 @@ cc_library_static { shared_libs: [ "libcrypto", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } @@ -816,7 +812,6 @@ cc_test { "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_log", - "libbt-audio-hal-interface", "libbt-common", "libbt-platform-protos-lite", "libchrome", @@ -825,6 +820,7 @@ cc_test { "libflatbuffers-cpp", "libgmock", "libosi", + "libudrv-uipc", "server_configurable_flags", ], sanitize: { @@ -871,6 +867,7 @@ cc_test { ":TestMockStackL2cap", ":TestStubOsi", "gmap/gmap_client.cc", + "gmap/gmap_server.cc", "le_audio/audio_hal_client/audio_hal_client_test.cc", "le_audio/audio_hal_client/audio_sink_hal_client.cc", "le_audio/audio_hal_client/audio_source_hal_client.cc", diff --git a/system/bta/ag/bta_ag_int.h b/system/bta/ag/bta_ag_int.h index 06caf10be9..f6026815a6 100644 --- a/system/bta/ag/bta_ag_int.h +++ b/system/bta/ag/bta_ag_int.h @@ -34,7 +34,6 @@ #include "bta/include/bta_api.h" #include "bta/sys/bta_sys.h" #include "internal_include/bt_target.h" -#include "os/logging/log_adapter.h" #include "stack/include/bt_hdr.h" #include "stack/include/btm_api_types.h" #include "stack/include/sdp_status.h" diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc index c96b867c71..58b7215a04 100644 --- a/system/bta/ag/bta_ag_rfc.cc +++ b/system/bta/ag/bta_ag_rfc.cc @@ -31,7 +31,6 @@ #include "bta/ag/bta_ag_int.h" #include "bta/include/bta_sec_api.h" #include "bta_api.h" -#include "os/logging/log_adapter.h" #include "stack/include/main_thread.h" #include "stack/include/port_api.h" #include "types/raw_address.h" diff --git a/system/bta/aics/Android.bp b/system/bta/aics/Android.bp index 33bd649d13..acb6b4945b 100644 --- a/system/bta/aics/Android.bp +++ b/system/bta/aics/Android.bp @@ -4,7 +4,7 @@ cc_library_headers { host_supported: true, vendor_available: true, // remove when https://r.android.com/3302734 is merged visibility: ["//packages/modules/Bluetooth:__subpackages__"], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "33", } @@ -27,6 +27,6 @@ cc_library { export_header_lib_headers: ["aics_headers"], host_supported: true, visibility: ["//packages/modules/Bluetooth:__subpackages__"], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "33", } diff --git a/system/bta/av/bta_av_main.cc b/system/bta/av/bta_av_main.cc index c9276a6564..d760b113bf 100644 --- a/system/bta/av/bta_av_main.cc +++ b/system/bta/av/bta_av_main.cc @@ -53,7 +53,6 @@ #include "btif/include/btif_config.h" #include "hardware/bt_av.h" #include "internal_include/bt_target.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/list.h" diff --git a/system/bta/csis/csis_client.cc b/system/bta/csis/csis_client.cc index aba46a68c6..916b1c0c56 100644 --- a/system/bta/csis/csis_client.cc +++ b/system/bta/csis/csis_client.cc @@ -59,7 +59,6 @@ #include "internal_include/bt_trace.h" #include "main/shim/le_scanning_manager.h" #include "neighbor_inquiry.h" -#include "os/logging/log_adapter.h" #include "osi/include/osi.h" #include "osi/include/stack_power_telemetry.h" #include "stack/btm/btm_sec.h" diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 7a931a6248..edfbe4bf97 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -45,6 +45,7 @@ #include "bta/sys/bta_sys.h" #include "btif/include/btif_dm.h" #include "btif/include/stack_manager_t.h" +#include "gd/os/rand.h" #include "hci/controller_interface.h" #include "internal_include/bt_target.h" #include "main/shim/acl_api.h" @@ -116,6 +117,14 @@ static const char kPropertySniffOffloadEnabled[] = "persist.bluetooth.sniff_offl #define BTA_DM_SWITCH_DELAY_TIMER_MS 500 #endif +/* New swich delay values behind flag extend_and_randomize_role_switch_delay (in milliseconds) */ +#ifndef BTA_DM_MAX_SWITCH_DELAY_MS +#define BTA_DM_MAX_SWITCH_DELAY_MS 1500 +#endif +#ifndef BTA_DM_MIN_SWITCH_DELAY_MS +#define BTA_DM_MIN_SWITCH_DELAY_MS 1000 +#endif + /* Sysprop path for page timeout */ #ifndef PROPERTY_PAGE_TIMEOUT #define PROPERTY_PAGE_TIMEOUT "bluetooth.core.classic.page_timeout" @@ -1174,8 +1183,15 @@ static void bta_dm_adjust_roles(bool delay_role_switch) { break; } } else { - alarm_set_on_mloop(bta_dm_cb.switch_delay_timer, BTA_DM_SWITCH_DELAY_TIMER_MS, - bta_dm_delay_role_switch_cback, NULL); + uint64_t delay = BTA_DM_SWITCH_DELAY_TIMER_MS; + if (com::android::bluetooth::flags::extend_and_randomize_role_switch_delay()) { + delay = bluetooth::os::GenerateRandom() % + (BTA_DM_MAX_SWITCH_DELAY_MS - BTA_DM_MIN_SWITCH_DELAY_MS) + + BTA_DM_MIN_SWITCH_DELAY_MS; + } + log::debug("Set timer to delay role switch:{}", delay); + alarm_set_on_mloop(bta_dm_cb.switch_delay_timer, delay, bta_dm_delay_role_switch_cback, + NULL); } } } diff --git a/system/bta/dm/bta_dm_device_search.cc b/system/bta/dm/bta_dm_device_search.cc index b11200a074..0dded3c7db 100644 --- a/system/bta/dm/bta_dm_device_search.cc +++ b/system/bta/dm/bta_dm_device_search.cc @@ -33,7 +33,6 @@ #include "common/strings.h" #include "device/include/interop.h" #include "main/shim/dumpsys.h" -#include "os/logging/log_adapter.h" #include "stack/btm/neighbor_inquiry.h" #include "stack/include/bt_dev_class.h" #include "stack/include/bt_name.h" @@ -343,7 +342,7 @@ static void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) std::format("status:{} state:{} name:\"{}\"", hci_status_code_text(remote_name_msg.hci_status), bta_dm_state_text(bta_dm_search_get_state()), - PRIVATE_NAME(reinterpret_cast<char const*>(remote_name_msg.bd_name)))); + reinterpret_cast<char const*>(remote_name_msg.bd_name))); tBTM_INQ_INFO* p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); diff --git a/system/bta/dm/bta_dm_disc.cc b/system/bta/dm/bta_dm_disc.cc index 2580e3a2da..0ce2062ff8 100644 --- a/system/bta/dm/bta_dm_disc.cc +++ b/system/bta/dm/bta_dm_disc.cc @@ -36,7 +36,6 @@ #include "device/include/interop.h" #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/btm/btm_dev.h" #include "stack/include/bt_name.h" diff --git a/system/bta/gmap/gmap_client.cc b/system/bta/gmap/gmap_client.cc index 0589b6a759..0a1210d413 100644 --- a/system/bta/gmap/gmap_client.cc +++ b/system/bta/gmap/gmap_client.cc @@ -36,10 +36,8 @@ using namespace bluetooth; using bluetooth::le_audio::GmapClient; bool GmapClient::is_offloader_support_gmap_ = false; -void GmapClient::AddFromStorage(const RawAddress &addr, const uint8_t role, - const uint16_t role_handle, const uint8_t UGT_feature, - const uint16_t UGT_feature_handle) { - addr_ = addr; +void GmapClient::AddFromStorage(uint8_t role, uint16_t role_handle, uint8_t UGT_feature, + uint16_t UGT_feature_handle) { role_ = role; role_handle_ = role_handle; UGT_feature_ = UGT_feature; @@ -60,8 +58,8 @@ bool GmapClient::IsGmapClientEnabled() { bool system_prop = osi_property_get_bool("bluetooth.profile.gmap.enabled", false); bool result = flag && system_prop && is_offloader_support_gmap_; - log::info("GmapClientEnabled={}, flag={}, system_prop={}, offloader_support={}", result, - system_prop, flag, GmapClient::is_offloader_support_gmap_); + log::info("GmapClientEnabled={}, flag={}, system_prop={}, offloader_support={}", result, flag, + system_prop, GmapClient::is_offloader_support_gmap_); return result; } @@ -90,14 +88,14 @@ bool GmapClient::parseAndSaveUGTFeature(uint16_t len, const uint8_t *value) { return true; } -std::bitset<8> GmapClient::getRole() { return role_; } +std::bitset<8> GmapClient::getRole() const { return role_; } -uint16_t GmapClient::getRoleHandle() { return role_handle_; } +uint16_t GmapClient::getRoleHandle() const { return role_handle_; } void GmapClient::setRoleHandle(uint16_t handle) { role_handle_ = handle; } -std::bitset<8> GmapClient::getUGTFeature() { return UGT_feature_; } +std::bitset<8> GmapClient::getUGTFeature() const { return UGT_feature_; } -uint16_t GmapClient::getUGTFeatureHandle() { return UGT_feature_handle_; } +uint16_t GmapClient::getUGTFeatureHandle() const { return UGT_feature_handle_; } void GmapClient::setUGTFeatureHandle(uint16_t handle) { UGT_feature_handle_ = handle; } diff --git a/system/bta/gmap/gmap_client_test.cc b/system/bta/gmap/gmap_client_test.cc index 68aec5caf5..bc497da0a9 100644 --- a/system/bta/gmap/gmap_client_test.cc +++ b/system/bta/gmap/gmap_client_test.cc @@ -68,7 +68,7 @@ TEST_F(GmapClientTest, test_add_from_storage) { const uint16_t role_handle = 2; const uint8_t UGT_feature = 0b0011; const uint16_t UGT_feature_handle = 4; - gmapClient.AddFromStorage(addr, role, role_handle, UGT_feature, UGT_feature_handle); + gmapClient.AddFromStorage(role, role_handle, UGT_feature, UGT_feature_handle); ASSERT_EQ(gmapClient.getRole(), role); ASSERT_EQ(gmapClient.getRoleHandle(), role_handle); ASSERT_EQ(gmapClient.getUGTFeature(), UGT_feature); diff --git a/system/bta/gmap/gmap_server.cc b/system/bta/gmap/gmap_server.cc index 407e50147b..1851355fe1 100644 --- a/system/bta/gmap/gmap_server.cc +++ b/system/bta/gmap/gmap_server.cc @@ -60,8 +60,8 @@ bool GmapServer::IsGmapServerEnabled() { bool system_prop = osi_property_get_bool("bluetooth.profile.gmap.enabled", false); bool result = flag && system_prop && is_offloader_support_gmap_; - log::info("GmapServerEnabled={}, flag={}, system_prop={}, offloader_support={}", result, - system_prop, flag, GmapServer::is_offloader_support_gmap_); + log::info("GmapServerEnabled={}, flag={}, system_prop={}, offloader_support={}", result, flag, + system_prop, GmapServer::is_offloader_support_gmap_); return result; } diff --git a/system/bta/groups/groups.cc b/system/bta/groups/groups.cc index 2390a2793e..3d79cdf8d3 100644 --- a/system/bta/groups/groups.cc +++ b/system/bta/groups/groups.cc @@ -35,7 +35,6 @@ #include "bta_groups.h" #include "btif/include/btif_profile_storage.h" -#include "os/logging/log_adapter.h" #include "stack/include/bt_types.h" #include "types/bluetooth/uuid.h" #include "types/raw_address.h" diff --git a/system/bta/has/has_ctp.cc b/system/bta/has/has_ctp.cc index dbe41442d5..cb99272707 100644 --- a/system/bta/has/has_ctp.cc +++ b/system/bta/has/has_ctp.cc @@ -28,7 +28,6 @@ #include <vector> #include "has_preset.h" -#include "os/logging/log_adapter.h" #include "stack/include/bt_types.h" #include "types/raw_address.h" diff --git a/system/bta/hearing_aid/hearing_aid.cc b/system/bta/hearing_aid/hearing_aid.cc index 340e08d992..245b095b07 100644 --- a/system/bta/hearing_aid/hearing_aid.cc +++ b/system/bta/hearing_aid/hearing_aid.cc @@ -63,7 +63,6 @@ #include "internal_include/bt_trace.h" #include "l2cap_types.h" #include "main/shim/entry.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" #include "profiles_api.h" diff --git a/system/bta/hf_client/bta_hf_client_at.cc b/system/bta/hf_client/bta_hf_client_at.cc index 700e4ab08a..95d871c17c 100644 --- a/system/bta/hf_client/bta_hf_client_at.cc +++ b/system/bta/hf_client/bta_hf_client_at.cc @@ -32,7 +32,6 @@ #include "bta_hfp_api.h" #include "bta_sys.h" #include "btm_api_types.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/compat.h" @@ -41,6 +40,11 @@ #include "stack/include/acl_api.h" #include "stack/include/port_api.h" +#define PRIVATE_CELL(number) \ + (number.replace(0, (number.size() > 2) ? number.size() - 2 : 0, \ + (number.size() > 2) ? number.size() - 2 : 0, '*') \ + .c_str()) + /* Uncomment to enable AT traffic dumping */ /* #define BTA_HF_CLIENT_AT_DUMP 1 */ diff --git a/system/bta/hh/bta_hh_act.cc b/system/bta/hh/bta_hh_act.cc index 4e685a5b8e..7c19f91c17 100644 --- a/system/bta/hh/bta_hh_act.cc +++ b/system/bta/hh/bta_hh_act.cc @@ -926,12 +926,6 @@ void bta_hh_maint_dev_act(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { /* initialize callback data */ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE) { tBT_TRANSPORT transport = p_data->api_maintdev.link_spec.transport; - if (!com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - transport = get_btm_client_interface().ble.BTM_UseLeLink( - p_data->api_maintdev.link_spec.addrt.bda) - ? BT_TRANSPORT_LE - : BT_TRANSPORT_BR_EDR; - } if (transport == BT_TRANSPORT_LE) { p_cb->link_spec.transport = BT_TRANSPORT_LE; dev_info.handle = bta_hh_le_add_device(p_cb, p_dev_info); diff --git a/system/bta/hh/bta_hh_le.cc b/system/bta/hh/bta_hh_le.cc index ea90ecfafc..cb3cb4c65a 100644 --- a/system/bta/hh/bta_hh_le.cc +++ b/system/bta/hh/bta_hh_le.cc @@ -1771,6 +1771,11 @@ void bta_hh_gatt_close(tBTA_HH_DEV_CB* p_cb, const tBTA_HH_DATA* p_data) { if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable) { bta_hh_disc_cmpl(); } else { + if (com::android::bluetooth::flags::hogp_reconnection()) { + // reconnection is handled in btif_hh.cc:btif_hh_disconnected + return; + } + switch (le_close->reason) { case GATT_CONN_FAILED_ESTABLISHMENT: case GATT_CONN_TERMINATE_PEER_USER: diff --git a/system/bta/include/bta_jv_api.h b/system/bta/include/bta_jv_api.h index 8978ab00c2..08709e1900 100644 --- a/system/bta/include/bta_jv_api.h +++ b/system/bta/include/bta_jv_api.h @@ -698,7 +698,7 @@ tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg, u ******************************************************************************/ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddress& peer_bd_addr, tBTA_JV_RFCOMM_CBACK* p_cback, - uint32_t rfcomm_slot_id, RfcommCfgInfo cfg); + uint32_t rfcomm_slot_id, RfcommCfgInfo cfg, uint32_t app_uid); /******************************************************************************* * @@ -729,7 +729,7 @@ tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t handle, uint32_t rfcomm_slot_id); ******************************************************************************/ tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t max_session, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id, - RfcommCfgInfo cfg); + RfcommCfgInfo cfg, uint32_t app_uid); /******************************************************************************* * diff --git a/system/bta/include/bta_le_audio_api.h b/system/bta/include/bta_le_audio_api.h index de11131bae..52a3f7d83c 100644 --- a/system/bta/include/bta_le_audio_api.h +++ b/system/bta/include/bta_le_audio_api.h @@ -86,8 +86,9 @@ public: const std::vector<uint8_t>& handles, const std::vector<uint8_t>& sink_pacs, const std::vector<uint8_t>& source_pacs, - const std::vector<uint8_t>& ases); + const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap); static bool GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out); + static bool GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out); static bool GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out); static bool GetSourcePacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out); static bool GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out); diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc index 7b6fa38ca8..7c3cb13d47 100644 --- a/system/bta/jv/bta_jv_act.cc +++ b/system/bta/jv/bta_jv_act.cc @@ -1512,7 +1512,7 @@ static void bta_jv_port_event_cl_cback(uint32_t code, uint16_t port_handle) { /* Client initiates an RFCOMM connection */ void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddress& peer_bd_addr, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id, - RfcommCfgInfo cfg) { + RfcommCfgInfo cfg, uint32_t app_uid) { uint16_t handle = 0; uint32_t event_mask = BTA_JV_RFC_EV_MASK; PortSettings port_settings; @@ -1527,14 +1527,12 @@ void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddre }, }; - if (com::android::bluetooth::flags::rfcomm_always_use_mitm()) { - // Update security service record for RFCOMM client so that - // secure RFCOMM connection will be authenticated with MTIM protection - // while creating the L2CAP connection. - get_btm_client_interface().security.BTM_SetSecurityLevel( - true, "RFC_MUX", BTM_SEC_SERVICE_RFC_MUX, sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, - 0); - } + // Update security service record for RFCOMM client so that + // secure RFCOMM connection will be authenticated with MTIM protection + // while creating the L2CAP connection. + get_btm_client_interface().security.BTM_SetSecurityLevel(true, "RFC_MUX", BTM_SEC_SERVICE_RFC_MUX, + sec_mask, BT_PSM_RFCOMM, + BTM_SEC_PROTO_RFCOMM, 0); if (RFCOMM_CreateConnectionWithSecurity( UUID_SERVCLASS_SERIAL_PORT, remote_scn, false, BTA_JV_DEF_RFC_MTU, peer_bd_addr, @@ -1551,6 +1549,9 @@ void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddre p_pcb->rfcomm_slot_id = rfcomm_slot_id; bta_jv.rfc_cl_init.use_co = true; + if (PORT_SetAppUid(handle, app_uid) != PORT_SUCCESS) { + log::warn("Unable to set app_uid for port handle:{}", handle); + } if (PORT_SetEventMaskAndCallback(handle, event_mask, bta_jv_port_event_cl_cback) != PORT_SUCCESS) { log::warn("Unable to set RFCOMM client event mask and callback handle:{}", handle); @@ -1845,7 +1846,7 @@ static tBTA_JV_PCB* bta_jv_add_rfc_port(tBTA_JV_RFC_CB* p_cb, tBTA_JV_PCB* p_pcb /* waits for an RFCOMM client to connect */ void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t max_session, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id, - RfcommCfgInfo cfg) { + RfcommCfgInfo cfg, uint32_t app_uid) { uint16_t handle = 0; uint32_t event_mask = BTA_JV_RFC_EV_MASK; PortSettings port_settings; @@ -1879,6 +1880,9 @@ void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t ma evt_data.handle = p_cb->handle; evt_data.use_co = true; + if (PORT_SetAppUid(handle, app_uid) != PORT_SUCCESS) { + log::warn("Unable to set app_uid for port handle:{}", handle); + } if (PORT_ClearKeepHandleFlag(handle) != PORT_SUCCESS) { log::warn("Unable to clear RFCOMM server keep handle flag handle:{}", handle); } diff --git a/system/bta/jv/bta_jv_api.cc b/system/bta/jv/bta_jv_api.cc index bf240a9834..3110869bb1 100644 --- a/system/bta/jv/bta_jv_api.cc +++ b/system/bta/jv/bta_jv_api.cc @@ -415,7 +415,7 @@ tBTA_JV_STATUS BTA_JvL2capWrite(uint32_t handle, uint32_t req_id, BT_HDR* msg, u ******************************************************************************/ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddress& peer_bd_addr, tBTA_JV_RFCOMM_CBACK* p_cback, - uint32_t rfcomm_slot_id, RfcommCfgInfo cfg) { + uint32_t rfcomm_slot_id, RfcommCfgInfo cfg, uint32_t app_uid) { log::verbose("remote_scn:{}, peer_bd_addr:{}, rfcomm_slot_id:{}", remote_scn, peer_bd_addr, rfcomm_slot_id); @@ -424,7 +424,7 @@ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask, uint8_t remote_scn, } do_in_main_thread(Bind(&bta_jv_rfcomm_connect, sec_mask, remote_scn, peer_bd_addr, p_cback, - rfcomm_slot_id, cfg)); + rfcomm_slot_id, cfg, app_uid)); return tBTA_JV_STATUS::SUCCESS; } @@ -470,7 +470,7 @@ tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t handle, uint32_t rfcomm_slot_id) { ******************************************************************************/ tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t max_session, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id, - RfcommCfgInfo cfg) { + RfcommCfgInfo cfg, uint32_t app_uid) { log::verbose("local_scn:{}, rfcomm_slot_id:{}", local_scn, rfcomm_slot_id); if (p_cback == NULL) { @@ -486,7 +486,7 @@ tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask, uint8_t local_scn, uin } do_in_main_thread(Bind(&bta_jv_rfcomm_start_server, sec_mask, local_scn, max_session, p_cback, - rfcomm_slot_id, cfg)); + rfcomm_slot_id, cfg, app_uid)); return tBTA_JV_STATUS::SUCCESS; } diff --git a/system/bta/jv/bta_jv_int.h b/system/bta/jv/bta_jv_int.h index 49ccd976b0..1295b88716 100644 --- a/system/bta/jv/bta_jv_int.h +++ b/system/bta/jv/bta_jv_int.h @@ -166,11 +166,11 @@ void bta_jv_l2cap_write(uint32_t handle, uint32_t req_id, BT_HDR* msg, uint32_t tBTA_JV_L2C_CB* p_cb); void bta_jv_rfcomm_connect(tBTA_SEC sec_mask, uint8_t remote_scn, const RawAddress& peer_bd_addr, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id, - RfcommCfgInfo cfg); + RfcommCfgInfo cfg, uint32_t app_uid); void bta_jv_rfcomm_close(uint32_t handle, uint32_t rfcomm_slot_id); void bta_jv_rfcomm_start_server(tBTA_SEC sec_mask, uint8_t local_scn, uint8_t max_session, tBTA_JV_RFCOMM_CBACK* p_cback, uint32_t rfcomm_slot_id, - RfcommCfgInfo cfg); + RfcommCfgInfo cfg, uint32_t app_uid); void bta_jv_rfcomm_stop_server(uint32_t handle, uint32_t rfcomm_slot_id); void bta_jv_rfcomm_write(uint32_t handle, uint32_t req_id, tBTA_JV_RFC_CB* p_cb, tBTA_JV_PCB* p_pcb); diff --git a/system/bta/le_audio/broadcaster/broadcaster.cc b/system/bta/le_audio/broadcaster/broadcaster.cc index da8c3ddace..e72757a129 100644 --- a/system/bta/le_audio/broadcaster/broadcaster.cc +++ b/system/bta/le_audio/broadcaster/broadcaster.cc @@ -949,6 +949,17 @@ public: log::info("Start queued broadcast."); StartAudioBroadcast(broadcast_id); } + } else { + // If audio resumes before ISO release, trigger broadcast start + if (audio_state_ == AudioState::ACTIVE) { + cancelBroadcastTimers(); + UpdateAudioActiveStateInPublicAnnouncement(); + + for (auto& broadcast_pair : broadcasts_) { + auto& broadcast = broadcast_pair.second; + broadcast->ProcessMessage(BroadcastStateMachine::Message::START, nullptr); + } + } } if (queued_create_broadcast_request_) { @@ -1394,10 +1405,19 @@ private: return; } + /* If there is ongoing ISO traffic, it might be not torn down unicast stream. Resume of + * broadcast stream would be triggered from IsoTrafficEventCb context, once ISO would be + * released. + */ + if (!IsAnyoneStreaming() && instance->is_iso_running_) { + log::debug("iso is busy, skip resume request"); + return; + } + instance->cancelBroadcastTimers(); instance->UpdateAudioActiveStateInPublicAnnouncement(); - /* In case of double call of resume when broadcast are already in streaming states */ + /* In case of double call of resume when broadcasts are already in streaming states */ if (IsAnyoneStreaming()) { log::debug("broadcasts are already streaming"); instance->le_audio_source_hal_client_->ConfirmStreamingRequest(); diff --git a/system/bta/le_audio/broadcaster/broadcaster_test.cc b/system/bta/le_audio/broadcaster/broadcaster_test.cc index c228ac68ea..8a4acba946 100644 --- a/system/bta/le_audio/broadcaster/broadcaster_test.cc +++ b/system/bta/le_audio/broadcaster/broadcaster_test.cc @@ -1454,6 +1454,78 @@ TEST_F(BroadcasterTest, AudioResumeWhileStreaming) { Mock::VerifyAndClearExpectations(mock_codec_manager_); } +TEST_F(BroadcasterTest, AudioResumeAfterSuspend) { + com::android::bluetooth::flags::provider_->leaudio_big_depends_on_audio_state(true); + + EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true)) + .Times(1); + LeAudioSourceAudioHalClient::Callbacks* audio_receiver; + EXPECT_CALL(*mock_audio_source_, Start) + .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true))) + .WillRepeatedly(Return(false)); + auto broadcast_id = InstantiateBroadcast(); + + ASSERT_NE(audio_receiver, nullptr); + + // OnAudioResume cause state machine go to STREAMING state so BIG creation + EXPECT_CALL(mock_broadcaster_callbacks_, + OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) + .Times(1); + audio_receiver->OnAudioResume(); + Mock::VerifyAndClearExpectations(mock_audio_source_); + Mock::VerifyAndClearExpectations(mock_codec_manager_); + + // OnAudioSuspend cause starting the BIG termination timer + audio_receiver->OnAudioSuspend(); + ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop")); + ASSERT_TRUE(big_terminate_timer_->cb != nullptr); + ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); + + // BIG termination timer execution, state machine go to CONFIGURED state so BIG terminated + EXPECT_CALL(mock_broadcaster_callbacks_, + OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED)) + .Times(1); + // Imitate execution of BIG termination timer + big_terminate_timer_->cb(big_terminate_timer_->data); + Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_); + + // OnAudioResume cause state machine go to STREAMING state so BIG creation + EXPECT_CALL(mock_broadcaster_callbacks_, + OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) + .Times(1); + audio_receiver->OnAudioResume(); + Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_); + + // OnAudioSuspend cause starting the BIG termination timer + audio_receiver->OnAudioSuspend(); + ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop")); + ASSERT_TRUE(big_terminate_timer_->cb != nullptr); + ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr); + + // BIG termination timer execution, state machine go to CONFIGURED state so BIG terminated + EXPECT_CALL(mock_broadcaster_callbacks_, + OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED)) + .Times(1); + // Imitate execution of BIG termination timer + big_terminate_timer_->cb(big_terminate_timer_->data); + + // Imitate busy ISO + iso_active_callback(true); + + EXPECT_CALL(mock_broadcaster_callbacks_, + OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) + .Times(0); + audio_receiver->OnAudioResume(); + Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_); + + // Verify if iso de-activation start streaming + EXPECT_CALL(mock_broadcaster_callbacks_, + OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING)) + .Times(1); + iso_active_callback(false); + Mock::VerifyAndClearExpectations(&mock_broadcaster_callbacks_); +} + // TODO: Add tests for: // ToRawPacket(BasicAudioAnnouncementData const& in, std::vector<uint8_t>& data) diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 7008676f9c..89b38e6bbb 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -1847,7 +1847,8 @@ public: int source_audio_location, int sink_supported_context_types, int source_supported_context_types, const std::vector<uint8_t>& handles, const std::vector<uint8_t>& sink_pacs, - const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases) { + const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases, + const std::vector<uint8_t>& gmap) { LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address); if (leAudioDevice) { @@ -1916,6 +1917,14 @@ public: log::warn("Could not load ases"); } + if (gmap.size() != 0) { + leAudioDevice->gmap_client_ = std::make_unique<GmapClient>(leAudioDevice->address_); + if (!le_audio::DeserializeGmap(leAudioDevice->gmap_client_.get(), gmap)) { + leAudioDevice->gmap_client_.reset(); + log::warn("Invalid GMAP storage for {}", leAudioDevice->address_); + } + } + leAudioDevice->autoconnect_flag_ = autoconnect; /* When adding from storage, make sure that autoconnect is used * by all the devices in the group. @@ -1929,6 +1938,11 @@ public: return SerializeHandles(leAudioDevice, out); } + bool GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { + LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr); + return SerializeGmap(leAudioDevice->gmap_client_.get(), out); + } + bool GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr); return SerializeSinkPacs(leAudioDevice, out); @@ -2330,9 +2344,11 @@ public: } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() && hdl == leAudioDevice->gmap_client_->getRoleHandle()) { leAudioDevice->gmap_client_->parseAndSaveGmapRole(len, value); + btif_storage_leaudio_update_gmap_bin(leAudioDevice->address_); } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() && hdl == leAudioDevice->gmap_client_->getUGTFeatureHandle()) { leAudioDevice->gmap_client_->parseAndSaveUGTFeature(len, value); + btif_storage_leaudio_update_gmap_bin(leAudioDevice->address_); } else { log::error("Unknown attribute read: 0x{:x}", hdl); } @@ -5322,9 +5338,37 @@ public: // Do not take the obsolete metadata remote_metadata.get(remote_other_direction).clear(); } else { - remote_metadata.get(remote_other_direction).unset_all(all_bidirectional_contexts); - remote_metadata.get(remote_other_direction) - .unset_all(single_direction_only_context_types); + // The other direction was opened when already in a bidirectional scenario that was not a + // VoIP or a regular Call. We need to figure out which direction metadata is the leading + // one. + // Note: We usually remove any bidirectional or the previous direction specific context + // from the previous direction metadata and replace it with the just-resumed + // direction (but still bidirectional) context. However when recording is started + // in a GAME scenario, we don't want to reconfigure to or mix the context with LIVE. + auto remote_game_uplink_available = + group->GetAvailableContexts(le_audio::types::kLeAudioDirectionSource) + .test(LeAudioContextType::GAME); + auto local_game_uplink_active = + (audio_sender_state_ == AudioState::STARTED) && + remote_metadata.sink.test(LeAudioContextType::GAME) && + remote_metadata.source.test_any(LeAudioContextType::LIVE | + LeAudioContextType::CONVERSATIONAL); + log::debug( + "Remote {} metadata change ({}) while having remote {} context ({}) in a " + "bidirectional scenario of {}, local_game_uplink_active: {}, " + "remote_game_uplink_available: {}", + remote_direction_str, ToString(remote_metadata.get(remote_direction)), + remote_other_direction_str, ToString(remote_metadata.get(remote_other_direction)), + ToString(configuration_context_type_), local_game_uplink_active, + remote_game_uplink_available); + if (local_game_uplink_active && remote_game_uplink_available) { + remote_metadata.source.clear(); + remote_metadata.source.set(LeAudioContextType::GAME); + } else { + remote_metadata.get(remote_other_direction).unset_all(all_bidirectional_contexts); + remote_metadata.get(remote_other_direction) + .unset_all(single_direction_only_context_types); + } } remote_metadata.get(remote_other_direction) @@ -6238,14 +6282,14 @@ private: * the session callbacks special action from this Module would be * required e.g. to Unicast handover. */ - if (!com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) { - if (!sink_monitor_mode_) { - local_metadata_context_types_.sink.clear(); - le_audio_sink_hal_client_->Stop(); - le_audio_sink_hal_client_.reset(); - } + if (com::android::bluetooth::flags::leaudio_use_audio_recording_listener() || + !sink_monitor_mode_) { + local_metadata_context_types_.sink.clear(); + le_audio_sink_hal_client_->Stop(); + le_audio_sink_hal_client_.reset(); } } + local_metadata_context_types_.source.clear(); configuration_context_type_ = LeAudioContextType::UNINITIALIZED; @@ -6544,14 +6588,12 @@ DeviceGroupsCallbacksImpl deviceGroupsCallbacksImpl; } // namespace -void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect, - int sink_audio_location, int source_audio_location, - int sink_supported_context_types, - int source_supported_context_types, - const std::vector<uint8_t>& handles, - const std::vector<uint8_t>& sink_pacs, - const std::vector<uint8_t>& source_pacs, - const std::vector<uint8_t>& ases) { +void LeAudioClient::AddFromStorage( + const RawAddress& addr, bool autoconnect, int sink_audio_location, + int source_audio_location, int sink_supported_context_types, + int source_supported_context_types, const std::vector<uint8_t>& handles, + const std::vector<uint8_t>& sink_pacs, const std::vector<uint8_t>& source_pacs, + const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap) { if (!instance) { log::error("Not initialized yet"); return; @@ -6559,7 +6601,7 @@ void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect, instance->AddFromStorage(addr, autoconnect, sink_audio_location, source_audio_location, sink_supported_context_types, source_supported_context_types, handles, - sink_pacs, source_pacs, ases); + sink_pacs, source_pacs, ases, gmap); } bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { @@ -6598,6 +6640,15 @@ bool LeAudioClient::GetAsesForStorage(const RawAddress& addr, std::vector<uint8_ return instance->GetAsesForStorage(addr, out); } +bool LeAudioClient::GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { + if (!instance) { + log::error("Not initialized yet"); + return false; + } + + return instance->GetGmapForStorage(addr, out); +} + bool LeAudioClient::IsLeAudioClientRunning(void) { return instance != nullptr; } bool LeAudioClient::IsLeAudioClientInStreaming(void) { @@ -6669,6 +6720,7 @@ void LeAudioClient::Initialize( void LeAudioClient::DebugDump(int fd) { std::scoped_lock<std::mutex> lock(instance_mutex); DeviceGroups::DebugDump(fd); + GmapServer::DebugDump(fd); dprintf(fd, "LeAudio Manager: \n"); if (instance) { diff --git a/system/bta/le_audio/client_linux.cc b/system/bta/le_audio/client_linux.cc index ff56a555b8..9908ef0a61 100644 --- a/system/bta/le_audio/client_linux.cc +++ b/system/bta/le_audio/client_linux.cc @@ -48,14 +48,12 @@ void LeAudioClient::Initialize( void LeAudioClient::Cleanup(void) {} LeAudioClient* LeAudioClient::Get(void) { return nullptr; } void LeAudioClient::DebugDump(int fd) {} -void LeAudioClient::AddFromStorage(const RawAddress& addr, bool autoconnect, - int sink_audio_location, int source_audio_location, - int sink_supported_context_types, - int source_supported_context_types, - const std::vector<uint8_t>& handles, - const std::vector<uint8_t>& sink_pacs, - const std::vector<uint8_t>& source_pacs, - const std::vector<uint8_t>& ases) {} +void LeAudioClient::AddFromStorage( + const RawAddress& addr, bool autoconnect, int sink_audio_location, + int source_audio_location, int sink_supported_context_types, + int source_supported_context_types, const std::vector<uint8_t>& handles, + const std::vector<uint8_t>& sink_pacs, const std::vector<uint8_t>& source_pacs, + const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap) {} bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { return false; } @@ -68,5 +66,8 @@ bool LeAudioClient::GetSourcePacsForStorage(const RawAddress& addr, std::vector< bool LeAudioClient::GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { return false; } +bool LeAudioClient::GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) { + return false; +} bool LeAudioClient::IsLeAudioClientRunning() { return false; } bool LeAudioClient::IsLeAudioClientInStreaming() { return false; } diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index 9977fec885..b956adec0e 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -25,6 +25,7 @@ #include <cstdint> #include <functional> #include <memory> +#include <optional> #include <ostream> #include <sstream> #include <string> @@ -39,6 +40,8 @@ #include "broadcaster/broadcaster_types.h" #include "bta_le_audio_api.h" #include "btm_iso_api_types.h" +#include "gmap_client.h" +#include "gmap_server.h" #include "hardware/bt_le_audio.h" #include "hci/controller_interface.h" #include "hci/hci_packets.h" @@ -137,6 +140,19 @@ public: osi_property_get_bool("bluetooth.leaudio.dual_bidirection_swb.supported", false); bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(GetCodecLocation()); UpdateOffloadCapability(offloading_preference); + + if (IsUsingCodecExtensibility()) { + codec_provider_info_ = + audio::le_audio::LeAudioClientInterface::Get()->GetCodecConfigProviderInfo(); + if (codec_provider_info_.has_value() && codec_provider_info_->allowAsymmetric && + codec_provider_info_->lowLatency) { + GmapClient::UpdateGmapOffloaderSupport(true); + GmapServer::UpdateGmapOffloaderSupport(true); + log::debug("Asymmetric configuration supported. Enabling offloader GMAP support."); + } else { + log::debug("Asymmetric configurations not supported. Not enabling offloader GMAP support."); + } + } } ~codec_manager_impl() { if (GetCodecLocation() != CodecLocation::HOST) { @@ -149,6 +165,10 @@ public: } CodecLocation GetCodecLocation(void) const { return codec_location_; } + std::optional<ProviderInfo> GetCodecConfigProviderInfo(void) const { + return codec_provider_info_; + } + bool IsDualBiDirSwbSupported(void) const { if (GetCodecLocation() == CodecLocation::ADSP) { // Whether dual bidirection swb is supported by property and for offload @@ -1094,6 +1114,8 @@ private: std::unordered_map<btle_audio_codec_index_t, uint8_t> btle_audio_codec_type_map_ = { {::bluetooth::le_audio::LE_AUDIO_CODEC_INDEX_SOURCE_LC3, types::kLeAudioCodingFormatLC3}}; + std::optional<ProviderInfo> codec_provider_info_; + std::vector<btle_audio_codec_config_t> codec_input_capa = {}; std::vector<btle_audio_codec_config_t> codec_output_capa = {}; int broadcast_target_config = -1; @@ -1138,26 +1160,24 @@ std::ostream& operator<<(std::ostream& os, if (req.sink_requirements.has_value()) { for (auto const& sink_req : req.sink_requirements.value()) { - os << "sink_req: {"; + os << ", sink_req: {"; os << ", target_latency: " << +sink_req.target_latency; os << ", target_Phy: " << +sink_req.target_Phy; - // os << sink_req.params.GetAsCoreCodecCapabilities(); os << "}"; } } else { - os << "sink_req: None"; + os << ", sink_req: None"; } if (req.source_requirements.has_value()) { for (auto const& source_req : req.source_requirements.value()) { - os << "source_req: {"; + os << ", source_req: {"; os << ", target_latency: " << +source_req.target_latency; os << ", target_Phy: " << +source_req.target_Phy; - // os << source_req.params.GetAsCoreCodecCapabilities(); os << "}"; } } else { - os << "source_req: None"; + os << ", source_req: None"; } os << "}"; @@ -1207,6 +1227,14 @@ types::CodecLocation CodecManager::GetCodecLocation(void) const { return pimpl_->codec_manager_impl_->GetCodecLocation(); } +std::optional<ProviderInfo> CodecManager::GetCodecConfigProviderInfo(void) const { + if (!pimpl_->IsRunning()) { + return std::nullopt; + } + + return pimpl_->codec_manager_impl_->GetCodecConfigProviderInfo(); +} + bool CodecManager::IsDualBiDirSwbSupported(void) const { if (!pimpl_->IsRunning()) { return false; diff --git a/system/bta/le_audio/codec_manager.h b/system/bta/le_audio/codec_manager.h index 1a86a9d4b0..27c2534216 100644 --- a/system/bta/le_audio/codec_manager.h +++ b/system/bta/le_audio/codec_manager.h @@ -60,8 +60,28 @@ struct broadcast_offload_config { uint16_t max_transport_latency; }; +struct ProviderInfo { + bool allowAsymmetric = false; + bool lowLatency = false; + + inline std::string toString() const { + std::ostringstream _aidl_os; + _aidl_os << "ProviderInfo{"; + _aidl_os << "allowAsymmetric: " << allowAsymmetric; + _aidl_os << ", lowLatency: " << lowLatency; + _aidl_os << "}"; + return _aidl_os.str(); + } +}; + class CodecManager { public: + enum Flags { + NONE = 0x00, + LOW_LATENCY, + ALLOW_ASYMMETRIC, + }; + struct UnicastConfigurationRequirements { ::bluetooth::le_audio::types::LeAudioContextType audio_context_type; std::optional<std::vector<types::acs_ac_record>> sink_pacs; @@ -75,6 +95,8 @@ public: std::optional<std::vector<DeviceDirectionRequirements>> sink_requirements; std::optional<std::vector<DeviceDirectionRequirements>> source_requirements; + + Flags flags; }; /* The provider function checks each possible configuration (from the set of @@ -103,6 +125,7 @@ public: const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& offloading_preference); void Stop(void); virtual types::CodecLocation GetCodecLocation(void) const; + virtual std::optional<ProviderInfo> GetCodecConfigProviderInfo(void) const; virtual bool IsDualBiDirSwbSupported(void) const; virtual bool UpdateCisConfiguration(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction); diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index 5770fdbea4..908848668d 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -25,6 +25,8 @@ #include "hci/controller_interface_mock.h" #include "hci/hci_packets.h" #include "internal_include/stack_config.h" +#include "le_audio/gmap_client.h" +#include "le_audio/gmap_server.h" #include "le_audio/le_audio_types.h" #include "le_audio_set_configuration_provider.h" #include "test/mock/mock_legacy_hci_interface.h" @@ -95,18 +97,22 @@ stack_config_t mock_stack_config{ const stack_config_t* stack_config_get_interface(void) { return &mock_stack_config; } -namespace bluetooth { -namespace audio { -namespace le_audio { +namespace bluetooth::audio::le_audio { OffloadCapabilities get_offload_capabilities() { return {*offload_capabilities, *offload_capabilities}; } -} // namespace le_audio -} // namespace audio -} // namespace bluetooth +std::optional<bluetooth::le_audio::ProviderInfo> LeAudioClientInterface::GetCodecConfigProviderInfo( + void) const { + return std::nullopt; +} +LeAudioClientInterface* LeAudioClientInterface::Get() { return nullptr; } +} // namespace bluetooth::audio::le_audio namespace bluetooth::le_audio { +void GmapClient::UpdateGmapOffloaderSupport(bool) {} +void GmapServer::UpdateGmapOffloaderSupport(bool) {} + class MockLeAudioSourceHalClient; MockLeAudioSourceHalClient* mock_le_audio_source_hal_client_; std::unique_ptr<LeAudioSourceAudioHalClient> owned_mock_le_audio_source_hal_client_; @@ -681,12 +687,16 @@ TEST_F(CodecManagerTestAdsp, test_capabilities_none) { TEST_F(CodecManagerTestAdsp, test_capabilities) { for (auto test_context : ::bluetooth::le_audio::types::kLeAudioContextAllTypesArray) { // Build the offloader capabilities vector using the configuration provider - // in HOST mode to get all the .json filce configuration entries. + // in HOST mode to get all the .json file configuration entries. std::vector<AudioSetConfiguration> offload_capabilities; AudioSetConfigurationProvider::Initialize(bluetooth::le_audio::types::CodecLocation::HOST); - for (auto& cap : *AudioSetConfigurationProvider::Get()->GetConfigurations(test_context)) { + auto all_local_configs = AudioSetConfigurationProvider::Get()->GetConfigurations(test_context); + ASSERT_NE(0lu, all_local_configs->size()); + + for (auto& cap : *all_local_configs) { offload_capabilities.push_back(*cap); } + ASSERT_NE(0u, offload_capabilities.size()); set_mock_offload_capabilities(offload_capabilities); // Clean up before the codec manager starts it in ADSP mode. diff --git a/system/bta/le_audio/device_groups.cc b/system/bta/le_audio/device_groups.cc index c3fd37b36d..c4000c16d7 100644 --- a/system/bta/le_audio/device_groups.cc +++ b/system/bta/le_audio/device_groups.cc @@ -34,6 +34,7 @@ #include "audio_hal_client/audio_hal_client.h" #include "bta/include/bta_gatt_api.h" +#include "bta/le_audio/gmap_server.h" #include "bta_csis_api.h" #include "bta_groups.h" #include "btif/include/btif_profile_storage.h" @@ -53,7 +54,6 @@ #include "le_audio_utils.h" #include "main/shim/entry.h" #include "metrics_collector.h" -#include "os/logging/log_adapter.h" #include "stack/include/btm_client_interface.h" #include "types/bt_transport.h" @@ -786,8 +786,8 @@ bool LeAudioDeviceGroup::GetPresentationDelay(uint32_t* delay, uint8_t direction } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase))); } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice))); - if (preferred_delay_min <= preferred_delay_max && preferred_delay_min > delay_min && - preferred_delay_min < delay_max) { + if (preferred_delay_min <= preferred_delay_max && preferred_delay_min >= delay_min && + preferred_delay_min <= delay_max) { *delay = preferred_delay_min; } else { *delay = delay_min; @@ -826,8 +826,11 @@ CodecManager::UnicastConfigurationRequirements LeAudioDeviceGroup::GetAudioSetConfigurationRequirements(types::LeAudioContextType ctx_type) const { auto new_req = CodecManager::UnicastConfigurationRequirements{ .audio_context_type = ctx_type, + .flags = CodecManager::Flags::NONE, }; + bool remote_has_gmap = false; + // Define a requirement for each location. Knowing codec specific // capabilities (i.e. multiplexing capability) the config provider can // determine the number of ASEs to activate. @@ -934,6 +937,25 @@ LeAudioDeviceGroup::GetAudioSetConfigurationRequirements(types::LeAudioContextTy } } } + + if (device->gmap_client_) { + remote_has_gmap = true; + } + } + + if ((ctx_type == ::bluetooth::le_audio::types::LeAudioContextType::GAME) && + GmapClient::IsGmapClientEnabled() && GmapServer::IsGmapServerEnabled() && remote_has_gmap) { + // Allow asymmetric configurations for the low latency GAME scenarios + new_req.flags = CodecManager::Flags(CodecManager::Flags::ALLOW_ASYMMETRIC | + CodecManager::Flags::LOW_LATENCY); + log::debug( + "GMAP is enabled. Set asymmetric flag for the GAME audio context configuration " + "requests."); + } else { + log::debug( + "GMAP is disabled, remote_has_gmap: {}, gmap_client_enabled: {}, gmap_server_enabled: " + "{}", + remote_has_gmap, GmapClient::IsGmapClientEnabled(), GmapServer::IsGmapServerEnabled()); } return new_req; diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc index 84253c6fd3..7edb4f1df1 100644 --- a/system/bta/le_audio/devices.cc +++ b/system/bta/le_audio/devices.cc @@ -53,7 +53,6 @@ #include "le_audio_log_history.h" #include "le_audio_utils.h" #include "main/shim/entry.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/properties.h" #include "stack/include/btm_client_interface.h" diff --git a/system/bta/le_audio/gmap_client.h b/system/bta/le_audio/gmap_client.h index ec3d431afe..4b98abb868 100644 --- a/system/bta/le_audio/gmap_client.h +++ b/system/bta/le_audio/gmap_client.h @@ -26,8 +26,8 @@ namespace bluetooth::le_audio { class GmapClient { public: - void AddFromStorage(const RawAddress& addr, const uint8_t role, const uint16_t role_handle, - const uint8_t UGT_feature, const uint16_t UGT_feature_handle); + void AddFromStorage(uint8_t role, uint16_t role_handle, uint8_t UGT_feature, + uint16_t UGT_feature_handle); void DebugDump(std::stringstream& stream); @@ -41,15 +41,15 @@ public: bool parseAndSaveUGTFeature(uint16_t len, const uint8_t* value); - std::bitset<8> getRole(); + std::bitset<8> getRole() const; - uint16_t getRoleHandle(); + uint16_t getRoleHandle() const; void setRoleHandle(uint16_t handle); - std::bitset<8> getUGTFeature(); + std::bitset<8> getUGTFeature() const; - uint16_t getUGTFeatureHandle(); + uint16_t getUGTFeatureHandle() const; void setUGTFeatureHandle(uint16_t handle); diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc index 2891a9a8d4..3e14dca5ef 100644 --- a/system/bta/le_audio/le_audio_client_test.cc +++ b/system/bta/le_audio/le_audio_client_test.cc @@ -3728,17 +3728,20 @@ TEST_F(UnicastTestNoInit, ConnectFailedDueToInvalidParameters) { std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); + std::vector<uint8_t> gmap_data; + LeAudioClient::GetGmapForStorage(test_address0, gmap_data); + EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { do_in_main_thread(base::Bind(&LeAudioClient::AddFromStorage, test_address0, autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft, codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); do_in_main_thread(base::Bind(&LeAudioClient::AddFromStorage, test_address1, autoconnect, codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); }); // Expect stored device0 to connect automatically (first directed connection ) @@ -3835,16 +3838,17 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsBroakenStorage) { std::vector<uint8_t> empty_buf; EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { - do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect, - codec_spec_conf::kLeAudioLocationFrontLeft, - codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff, - std::move(empty_buf), std::move(empty_buf), - std::move(empty_buf), std::move(empty_buf))); + do_in_main_thread(base::BindOnce( + &LeAudioClient::AddFromStorage, test_address0, autoconnect, + codec_spec_conf::kLeAudioLocationFrontLeft, codec_spec_conf::kLeAudioLocationFrontLeft, + 0xff, 0xff, std::move(empty_buf), std::move(empty_buf), std::move(empty_buf), + std::move(empty_buf), std::move(empty_buf))); do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect, codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff, std::move(empty_buf), std::move(empty_buf), - std::move(empty_buf), std::move(empty_buf))); + std::move(empty_buf), std::move(empty_buf), + std::move(empty_buf))); SyncOnMainLoop(); }); @@ -3975,17 +3979,20 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGrouped) { std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); + std::vector<uint8_t> gmap_data; + LeAudioClient::GetGmapForStorage(test_address0, gmap_data); + EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft, codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect, codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); SyncOnMainLoop(); }); @@ -4098,6 +4105,9 @@ TEST_F(UnicastTest, LoadStoredBandedHeadphones) { std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); + std::vector<uint8_t> gmap_data; + LeAudioClient::GetGmapForStorage(test_address0, gmap_data); + /* Disconnect & Cleanup */ DisconnectLeAudioWithAclClose(test_address0, conn_id); if (LeAudioClient::IsLeAudioClientRunning()) { @@ -4116,7 +4126,7 @@ TEST_F(UnicastTest, LoadStoredBandedHeadphones) { codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationMonoAudio, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); SyncOnMainLoop(); }); @@ -4221,17 +4231,20 @@ TEST_F(UnicastTestNoInit, ServiceChangedBeforeServiceIsConnected) { std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); + std::vector<uint8_t> gmap_data; + LeAudioClient::GetGmapForStorage(test_address0, gmap_data); + EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect, codec_spec_conf::kLeAudioLocationFrontLeft, codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect, codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); SyncOnMainLoop(); }); @@ -4347,18 +4360,21 @@ TEST_F(UnicastTestNoInit, LoadStoredEarbudsCsisGroupedDifferently) { std::vector<uint8_t> snk_pacs; LeAudioClient::GetSinkPacsForStorage(test_address0, snk_pacs); + std::vector<uint8_t> gmap_data; + LeAudioClient::GetGmapForStorage(test_address0, gmap_data); + // Load devices from the storage when storage API is called EXPECT_CALL(mock_storage_load, Call()).WillOnce([&]() { do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address0, autoconnect0, codec_spec_conf::kLeAudioLocationFrontLeft, codec_spec_conf::kLeAudioLocationFrontLeft, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); do_in_main_thread(base::BindOnce(&LeAudioClient::AddFromStorage, test_address1, autoconnect1, codec_spec_conf::kLeAudioLocationFrontRight, codec_spec_conf::kLeAudioLocationFrontRight, 0xff, 0xff, std::move(handles), std::move(snk_pacs), std::move(src_pacs), - std::move(ases))); + std::move(ases), std::move(gmap_data))); }); // Expect stored device0 to connect automatically @@ -12229,86 +12245,92 @@ TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsActive) { // Stop StopStreaming(group_id, true); - // Check if cache configuration is still present - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSink) - .size()); - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSource) - .size()); - - // Release, Sink HAL client should remain in monitor mode - EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1); - EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0); - LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); - SyncOnMainLoop(); + if (com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) { + // simulate suspend timeout passed, alarm executing + fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data); + SyncOnMainLoop(); + } else { + // Check if cache configuration is still present + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSink) + .size()); + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSource) + .size()); + + // Release, Sink HAL client should remain in monitor mode + EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1); + EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0); + LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); + SyncOnMainLoop(); - Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); - Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); + Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - // Re-initialize mock for destroyed hal client - RegisterSourceHalClientMock(); + // Re-initialize mock for destroyed hal client + RegisterSourceHalClientMock(); - // Setting group inactive, shall not change cached configuration - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSink) - .size()); - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSource) - .size()); + // Setting group inactive, shall not change cached configuration + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSink) + .size()); + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSource) + .size()); - EXPECT_CALL(mock_audio_hal_client_callbacks_, - OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink, - UnicastMonitorModeStatus::STREAMING_REQUESTED)) - .Times(1); + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink, + UnicastMonitorModeStatus::STREAMING_REQUESTED)) + .Times(1); - // Start streaming to trigger next group going to IDLE state - LocalAudioSinkResume(); + // Start streaming to trigger next group going to IDLE state + LocalAudioSinkResume(); - EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1); - LeAudioClient::Get()->GroupSetActive(group_id); - Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); - SyncOnMainLoop(); + EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1); + LeAudioClient::Get()->GroupSetActive(group_id); + Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + SyncOnMainLoop(); - Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id); - SyncOnMainLoop(); - Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH, group_id); + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - // Stop streaming and expect Service to be informed about straming suspension - EXPECT_CALL(mock_audio_hal_client_callbacks_, - OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink, - UnicastMonitorModeStatus::STREAMING_SUSPENDED)) - .Times(1); + // Stop streaming and expect Service to be informed about straming suspension + EXPECT_CALL(mock_audio_hal_client_callbacks_, + OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink, + UnicastMonitorModeStatus::STREAMING_SUSPENDED)) + .Times(1); - // Stop - StopStreaming(group_id, true); + // Stop + StopStreaming(group_id, true); - // Release, Sink HAL client should remain in monitor mode - EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1); - EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0); - LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); - SyncOnMainLoop(); + // Release, Sink HAL client should remain in monitor mode + EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1); + EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0); + LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); + SyncOnMainLoop(); - Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); - Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); + Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - // De-activate monitoring mode - EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1); - do_in_main_thread(base::BindOnce( - &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()), - bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */)); - SyncOnMainLoop(); - Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); + // De-activate monitoring mode + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(1); + do_in_main_thread(base::BindOnce( + &LeAudioClient::SetUnicastMonitorMode, base::Unretained(LeAudioClient::Get()), + bluetooth::le_audio::types::kLeAudioDirectionSink, false /* enable */)); + SyncOnMainLoop(); + Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); + } } TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) { @@ -12376,33 +12398,39 @@ TEST_F(UnicastTestHandoverMode, SetSinkMonitorModeWhileUnicastIsInactive) { // Stop StopStreaming(group_id, true); - // Check if cache configuration is still present - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSink) - .size()); - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSource) - .size()); - - // Release, Sink HAL client should remain in monitor mode - EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1); - EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0); - EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0); - LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); - SyncOnMainLoop(); + if (com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) { + // simulate suspend timeout passed, alarm executing + fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data); + SyncOnMainLoop(); + } else { + // Check if cache configuration is still present + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSink) + .size()); + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSource) + .size()); + + // Release, Sink HAL client should remain in monitor mode + EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop()).Times(1); + EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(1); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, Stop()).Times(0); + EXPECT_CALL(*mock_le_audio_sink_hal_client_, OnDestroyed()).Times(0); + LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown); + SyncOnMainLoop(); - Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); - Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); - Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); + Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_); + Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_); + Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_); - // Setting group inactive, shall not change cached configuration - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSink) - .size()); - ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) - ->confs.get(le_audio::types::kLeAudioDirectionSource) - .size()); + // Setting group inactive, shall not change cached configuration + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSink) + .size()); + ASSERT_TRUE(group->GetCachedConfiguration(types::LeAudioContextType::CONVERSATIONAL) + ->confs.get(le_audio::types::kLeAudioDirectionSource) + .size()); + } } TEST_F(UnicastTestHandoverMode, ClearSinkMonitorModeWhileUnicastIsActive) { diff --git a/system/bta/le_audio/le_audio_health_status.cc b/system/bta/le_audio/le_audio_health_status.cc index b0729a6f9c..79f1a4a93d 100644 --- a/system/bta/le_audio/le_audio_health_status.cc +++ b/system/bta/le_audio/le_audio_health_status.cc @@ -31,7 +31,6 @@ #include "devices.h" #include "hardware/bt_le_audio.h" #include "main/shim/metrics_api.h" -#include "os/logging/log_adapter.h" #include "types/raw_address.h" using bluetooth::common::ToString; diff --git a/system/bta/le_audio/le_audio_log_history.cc b/system/bta/le_audio/le_audio_log_history.cc index d6848f3f79..95998ca1e6 100644 --- a/system/bta/le_audio/le_audio_log_history.cc +++ b/system/bta/le_audio/le_audio_log_history.cc @@ -28,7 +28,6 @@ #include "common/circular_buffer.h" #include "common/strings.h" #include "main/shim/dumpsys.h" -#include "os/logging/log_adapter.h" #include "types/raw_address.h" using namespace bluetooth; diff --git a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc index 8e22ddb3ff..a76a58bb59 100644 --- a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc +++ b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc @@ -51,14 +51,14 @@ namespace bluetooth::le_audio { #ifdef __ANDROID__ static const std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> - kLeAudioSetConfigs = {{"/apex/com.android.btservices/etc/bluetooth/le_audio/" + kLeAudioSetConfigs = {{"/apex/com.android.bt/etc/bluetooth/le_audio/" "audio_set_configurations.bfbs", - "/apex/com.android.btservices/etc/bluetooth/le_audio/" + "/apex/com.android.bt/etc/bluetooth/le_audio/" "audio_set_configurations.json"}}; static const std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> - kLeAudioSetScenarios = {{"/apex/com.android.btservices/etc/bluetooth/" + kLeAudioSetScenarios = {{"/apex/com.android.bt/etc/bluetooth/" "le_audio/audio_set_scenarios.bfbs", - "/apex/com.android.btservices/etc/bluetooth/" + "/apex/com.android.bt/etc/bluetooth/" "le_audio/audio_set_scenarios.json"}}; #elif defined(TARGET_FLOSS) static const std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> diff --git a/system/bta/le_audio/le_audio_types_test.cc b/system/bta/le_audio/le_audio_types_test.cc index 70c29426ef..992a35d4c1 100644 --- a/system/bta/le_audio/le_audio_types_test.cc +++ b/system/bta/le_audio/le_audio_types_test.cc @@ -840,5 +840,45 @@ TEST(CodecConfigTest, test_invalid_codec_bits_per_sample) { LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE); } +TEST(CodecConfigTest, test_tmap_and_gmap_target_latency) { + /* TMAP: Media -> Higher reliability */ + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::MEDIA), + types::kTargetLatencyHigherReliability); + + /* TMAP: Live performance -> Low Latency */ + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::LIVE), + types::kTargetLatencyLower); + + /* TMAP: Call -> Balanced reliability */ + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::RINGTONE), + types::kTargetLatencyBalancedLatencyReliability); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::CONVERSATIONAL), + types::kTargetLatencyBalancedLatencyReliability); + + /* GMAP: Game -> Low Latency */ + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::GAME), + types::kTargetLatencyLower); + + /* Undefined for the rest of contexts */ + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::UNINITIALIZED), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::UNSPECIFIED), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::INSTRUCTIONAL), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::VOICEASSISTANTS), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::SOUNDEFFECTS), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::NOTIFICATIONS), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::ALERTS), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::EMERGENCYALARM), + types::kTargetLatencyUndefined); + ASSERT_EQ(utils::GetTargetLatencyForAudioContext(LeAudioContextType::RFU), + types::kTargetLatencyUndefined); +} + } // namespace types } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/le_audio_utils.h b/system/bta/le_audio/le_audio_utils.h index f7406a41a5..8feed29473 100644 --- a/system/bta/le_audio/le_audio_utils.h +++ b/system/bta/le_audio/le_audio_utils.h @@ -40,17 +40,19 @@ types::AudioContexts GetAudioContextsFromSinkMetadata( const std::vector<struct record_track_metadata_v7>& sink_metadata); inline uint8_t GetTargetLatencyForAudioContext(types::LeAudioContextType ctx) { switch (ctx) { - case types::LeAudioContextType::GAME: - FALLTHROUGH_INTENDED; - case types::LeAudioContextType::VOICEASSISTANTS: - FALLTHROUGH_INTENDED; + case types::LeAudioContextType::MEDIA: + return types::kTargetLatencyHigherReliability; + case types::LeAudioContextType::LIVE: FALLTHROUGH_INTENDED; - case types::LeAudioContextType::CONVERSATIONAL: - FALLTHROUGH_INTENDED; - case types::LeAudioContextType::RINGTONE: + case types::LeAudioContextType::GAME: return types::kTargetLatencyLower; + case types::LeAudioContextType::RINGTONE: + FALLTHROUGH_INTENDED; + case types::LeAudioContextType::CONVERSATIONAL: + return types::kTargetLatencyBalancedLatencyReliability; + default: return types::kTargetLatencyUndefined; } diff --git a/system/bta/le_audio/mock_codec_manager.cc b/system/bta/le_audio/mock_codec_manager.cc index addf45ba85..f1621e02c0 100644 --- a/system/bta/le_audio/mock_codec_manager.cc +++ b/system/bta/le_audio/mock_codec_manager.cc @@ -41,6 +41,13 @@ types::CodecLocation CodecManager::GetCodecLocation() const { return pimpl_->GetCodecLocation(); } +std::optional<ProviderInfo> CodecManager::GetCodecConfigProviderInfo(void) const { + if (!pimpl_) { + return std::nullopt; + } + return pimpl_->GetCodecConfigProviderInfo(); +} + bool CodecManager::IsDualBiDirSwbSupported(void) const { if (!pimpl_) { return false; diff --git a/system/bta/le_audio/mock_codec_manager.h b/system/bta/le_audio/mock_codec_manager.h index 3203f33257..27db5c399a 100644 --- a/system/bta/le_audio/mock_codec_manager.h +++ b/system/bta/le_audio/mock_codec_manager.h @@ -38,6 +38,8 @@ public: virtual ~MockCodecManager() = default; MOCK_METHOD((bluetooth::le_audio::types::CodecLocation), GetCodecLocation, (), (const)); + MOCK_METHOD(std::optional<bluetooth::le_audio::ProviderInfo>, GetCodecConfigProviderInfo, (), + (const)); MOCK_METHOD((bool), IsDualBiDirSwbSupported, (), (const)); MOCK_METHOD((bool), UpdateActiveUnicastAudioHalClient, diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc index c44e3098c7..2fb2963149 100644 --- a/system/bta/le_audio/state_machine.cc +++ b/system/bta/le_audio/state_machine.cc @@ -48,7 +48,6 @@ #include "le_audio_health_status.h" #include "le_audio_log_history.h" #include "le_audio_types.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/osi.h" #include "osi/include/properties.h" diff --git a/system/bta/le_audio/storage_helper.cc b/system/bta/le_audio/storage_helper.cc index 159580d456..d48ec25363 100644 --- a/system/bta/le_audio/storage_helper.cc +++ b/system/bta/le_audio/storage_helper.cc @@ -437,4 +437,94 @@ bool DeserializeHandles(LeAudioDevice* leAudioDevice, const std::vector<uint8_t> leAudioDevice->known_service_handles_ = true; return true; } + +static constexpr uint8_t LEAUDIO_GMAP_STORAGE_V1_LAYOUT_MAGIC = 0x01; +static constexpr uint8_t LEAUDIO_GMAP_STORAGE_V1_LAYOUT_SZ = 7; +static constexpr uint8_t LEAUDIO_GMAP_STORAGE_CURRENT_LAYOUT_MAGIC = + LEAUDIO_GMAP_STORAGE_V1_LAYOUT_MAGIC; + +static bool SerializeGmapV1(const GmapClient* gmapClient, std::vector<uint8_t>& out) { + if (gmapClient == nullptr) { + log::warn("GMAP client not available"); + return false; + } + + /* The total size */ + out.resize(LEAUDIO_GMAP_STORAGE_V1_LAYOUT_SZ); + auto* ptr = out.data(); + + /* header */ + UINT8_TO_STREAM(ptr, LEAUDIO_GMAP_STORAGE_V1_LAYOUT_MAGIC); + + /* handles */ + UINT16_TO_STREAM(ptr, gmapClient->getRoleHandle()); + UINT16_TO_STREAM(ptr, gmapClient->getUGTFeatureHandle()); + + /* role & features */ + UINT8_TO_STREAM(ptr, gmapClient->getRole().to_ulong()); + UINT8_TO_STREAM(ptr, gmapClient->getUGTFeature().to_ulong()); + + return true; +} + +bool SerializeGmap(const GmapClient* gmapClient, std::vector<uint8_t>& out) { + if (gmapClient == nullptr) { + log::warn("GMAP client not available"); + return false; + } + + if (LEAUDIO_GMAP_STORAGE_CURRENT_LAYOUT_MAGIC == LEAUDIO_GMAP_STORAGE_V1_LAYOUT_MAGIC) { + return SerializeGmapV1(gmapClient, out); + } + + log::warn("Invalid GMAP storage magic number {}", +LEAUDIO_GMAP_STORAGE_CURRENT_LAYOUT_MAGIC); +} + +bool DeserializeGmapV1(GmapClient* gmapClient, const std::vector<uint8_t>& in) { + if (in.size() != LEAUDIO_GMAP_STORAGE_V1_LAYOUT_SZ) { + log::warn("Invalid storage size for GMAP data. Got {}, expected {}", in.size(), + +LEAUDIO_GMAP_STORAGE_V1_LAYOUT_SZ); + return false; + } + + // Skip the magic number + auto* ptr = in.data() + 1; + + /* handles */ + uint16_t role_handle, ugt_feature_handle; + STREAM_TO_UINT16(role_handle, ptr); + STREAM_TO_UINT16(ugt_feature_handle, ptr); + + uint8_t role, ugt_feature; + STREAM_TO_UINT8(role, ptr); + STREAM_TO_UINT8(ugt_feature, ptr); + + gmapClient->AddFromStorage(role, role_handle, ugt_feature, ugt_feature_handle); + return true; +} + +bool DeserializeGmap(GmapClient* gmapClient, const std::vector<uint8_t>& in) { + if (gmapClient == nullptr) { + log::warn("GMAP client not available"); + return false; + } + + if (in.size() < 1) { + log::warn("GMAP storage is not available"); + return false; + } + + auto* ptr = in.data(); + uint8_t magic; + STREAM_TO_UINT8(magic, ptr); + + if (magic == LEAUDIO_GMAP_STORAGE_V1_LAYOUT_MAGIC) { + return DeserializeGmapV1(gmapClient, in); + } + + log::warn("Invalid GMAP storage magic number. Got {}, current {}", +magic, + +LEAUDIO_GMAP_STORAGE_CURRENT_LAYOUT_MAGIC); + return false; +} + } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/storage_helper.h b/system/bta/le_audio/storage_helper.h index 85418457c9..78868fa744 100644 --- a/system/bta/le_audio/storage_helper.h +++ b/system/bta/le_audio/storage_helper.h @@ -21,6 +21,7 @@ #include <vector> #include "devices.h" +#include "le_audio/gmap_client.h" namespace bluetooth::le_audio { bool SerializeSinkPacs(const LeAudioDevice* leAudioDevice, std::vector<uint8_t>& out); @@ -31,4 +32,6 @@ bool SerializeAses(const LeAudioDevice* leAudioDevice, std::vector<uint8_t>& out bool DeserializeAses(LeAudioDevice* leAudioDevice, const std::vector<uint8_t>& in); bool SerializeHandles(const LeAudioDevice* leAudioDevice, std::vector<uint8_t>& out); bool DeserializeHandles(LeAudioDevice* leAudioDevice, const std::vector<uint8_t>& in); +bool SerializeGmap(const GmapClient* gmap_server, std::vector<uint8_t>& out); +bool DeserializeGmap(GmapClient* gmap_server, const std::vector<uint8_t>& in); } // namespace bluetooth::le_audio diff --git a/system/bta/le_audio/storage_helper_test.cc b/system/bta/le_audio/storage_helper_test.cc index ef0a9ed172..9effb2b47f 100644 --- a/system/bta/le_audio/storage_helper_test.cc +++ b/system/bta/le_audio/storage_helper_test.cc @@ -309,4 +309,41 @@ TEST(StorageHelperTest, DeserializeHandles) { ASSERT_FALSE(DeserializeHandles(&leAudioDevice, invalidHandlesMagic)); ASSERT_FALSE(DeserializeHandles(&leAudioDevice, invalidHandles)); } + +TEST(StorageHelperTest, DeserializeGmapV1) { + // clang-format off + const std::vector<uint8_t> validHandles { + 0x01, // V1 Layout Magic + 0x0e, 0x11, // Role Handle + 0x0f, 0x11, // Feature Handle + 0x05, // Role value + 0x06, // Feature value + }; + const std::vector<uint8_t> invalidHandlesMagic { + 0x00, // Unknown Layout Magic + 0x0e, 0x11, // Role Handle + 0x0f, 0x11, // Feature Handle + 0x05, // Role value + 0x06, // Feature value + }; + const std::vector<uint8_t> invalidHandles { + 0x01, // V1 Layout Magic + 0x0e, 0x11, // Role Handle + 0x0f, 0x11, // Feature Handle + 0x05, // Role value + 0x06, // Feature value + 0x06, // corrupted + }; + + // clang-format on + RawAddress test_address0 = GetTestAddress(0); + GmapClient gmap(test_address0); + ASSERT_TRUE(DeserializeGmap(&gmap, validHandles)); + std::vector<uint8_t> serialize; + ASSERT_TRUE(SerializeGmap(&gmap, serialize)); + ASSERT_TRUE(serialize == validHandles); + + ASSERT_FALSE(DeserializeGmap(&gmap, invalidHandlesMagic)); + ASSERT_FALSE(DeserializeGmap(&gmap, invalidHandles)); +} } // namespace bluetooth::le_audio diff --git a/system/bta/ras/ras_utils.cc b/system/bta/ras/ras_utils.cc index 541149423d..e9d9ee863e 100644 --- a/system/bta/ras/ras_utils.cc +++ b/system/bta/ras/ras_utils.cc @@ -75,6 +75,7 @@ bool ParseControlPointCommand(ControlPointCommand* command, const uint8_t* value break; default: log::warn("unknown opcode 0x{:02x}", value[0]); + command->isValid_ = true; return false; } std::memcpy(command->parameter_, value + 1, len - 1); diff --git a/system/bta/test/common/btif_storage_mock.cc b/system/bta/test/common/btif_storage_mock.cc index b74b7678ea..3b7ee7d06e 100644 --- a/system/bta/test/common/btif_storage_mock.cc +++ b/system/bta/test/common/btif_storage_mock.cc @@ -41,6 +41,12 @@ void btif_storage_leaudio_update_pacs_bin(const RawAddress& addr) { btif_storage_interface->LeAudioUpdatePacs(addr); } +/** Store GMAP information */ +void btif_storage_leaudio_update_gmap_bin(const RawAddress& addr) { + log::assert_that(btif_storage_interface != nullptr, "Mock storage module not set!"); + btif_storage_interface->LeAudioUpdateGmap(addr); +} + void btif_storage_leaudio_update_ase_bin(const RawAddress& addr) { log::assert_that(btif_storage_interface != nullptr, "Mock storage module not set!"); btif_storage_interface->LeAudioUpdateAses(addr); diff --git a/system/bta/test/common/btif_storage_mock.h b/system/bta/test/common/btif_storage_mock.h index a715b43b70..c756336dab 100644 --- a/system/bta/test/common/btif_storage_mock.h +++ b/system/bta/test/common/btif_storage_mock.h @@ -28,6 +28,7 @@ class BtifStorageInterface { public: virtual void AddLeaudioAutoconnect(RawAddress const& addr, bool autoconnect) = 0; virtual void LeAudioUpdatePacs(RawAddress const& addr) = 0; + virtual void LeAudioUpdateGmap(RawAddress const& addr) = 0; virtual void LeAudioUpdateAses(RawAddress const& addr) = 0; virtual void LeAudioUpdateHandles(RawAddress const& addr) = 0; virtual void SetLeAudioLocations(RawAddress const& addr, uint32_t sink_location, @@ -57,6 +58,7 @@ public: MOCK_METHOD((void), AddLeaudioAutoconnect, (RawAddress const& addr, bool autoconnect), (override)); MOCK_METHOD((void), LeAudioUpdatePacs, (RawAddress const& addr), (override)); + MOCK_METHOD((void), LeAudioUpdateGmap, (RawAddress const& addr), (override)); MOCK_METHOD((void), LeAudioUpdateAses, (RawAddress const& addr), (override)); MOCK_METHOD((void), LeAudioUpdateHandles, (RawAddress const& addr), (override)); MOCK_METHOD((void), SetLeAudioLocations, diff --git a/system/bta/vc/devices.h b/system/bta/vc/devices.h index 4c0a105ee8..88c9d4c5e9 100644 --- a/system/bta/vc/devices.h +++ b/system/bta/vc/devices.h @@ -25,7 +25,6 @@ #include "bta/include/bta_gatt_api.h" #include "bta/vc/types.h" -#include "os/logging/log_adapter.h" #include "types/raw_address.h" namespace bluetooth { diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc index c381f1210a..17c88c3f17 100644 --- a/system/bta/vc/vc.cc +++ b/system/bta/vc/vc.cc @@ -20,6 +20,7 @@ #include <base/strings/string_number_conversions.h> #include <base/strings/string_util.h> #include <bluetooth/log.h> +#include <com_android_bluetooth_flags.h> #include <hardware/bt_gatt_types.h> #include <hardware/bt_vc.h> #include <stdio.h> @@ -934,6 +935,27 @@ public: } } + bool isPendingVolumeControlOperation(const RawAddress& addr) { + if (!com::android::bluetooth::flags::vcp_allow_set_same_volume_if_pending()) { + return false; + } + + if (std::find_if(ongoing_operations_.begin(), ongoing_operations_.end(), + [&addr](const VolumeOperation& op) { + auto it = find(op.devices_.begin(), op.devices_.end(), addr); + if (it != op.devices_.end()) { + bluetooth::log::debug( + "There is a pending volume operation {} for device {}", + op.operation_id_, addr); + return true; + } + return false; + }) != ongoing_operations_.end()) { + return true; + } + return false; + } + void RemovePendingVolumeControlOperations(const std::vector<RawAddress>& devices, int group_id) { bluetooth::log::debug(""); for (auto op = ongoing_operations_.begin(); op != ongoing_operations_.end();) { @@ -1156,7 +1178,8 @@ public: volume_control_devices_.FindByAddress(std::get<RawAddress>(addr_or_group_id)); if (dev != nullptr) { bluetooth::log::debug("Address: {}: isReady: {}", dev->address, dev->IsReady()); - if (dev->IsReady() && (dev->volume != volume)) { + if (dev->IsReady() && + ((dev->volume != volume) || isPendingVolumeControlOperation(dev->address))) { std::vector<RawAddress> devices = {dev->address}; RemovePendingVolumeControlOperations(devices, bluetooth::groups::kGroupUnknown); PrepareVolumeControlOperation(devices, bluetooth::groups::kGroupUnknown, false, opcode, @@ -1189,7 +1212,7 @@ public: continue; } - if (!dev->IsReady() || (dev->volume == volume)) { + if (!dev->IsReady() || ((dev->volume == volume) && !isPendingVolumeControlOperation(*it))) { it = devices.erase(it); volumeNotChanged = volumeNotChanged ? volumeNotChanged : (dev->volume == volume); deviceNotReady = deviceNotReady ? deviceNotReady : !dev->IsReady(); diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc index c9c6adc425..a6f4d60e7c 100644 --- a/system/bta/vc/vc_test.cc +++ b/system/bta/vc/vc_test.cc @@ -1703,6 +1703,47 @@ TEST_F(VolumeControlValueSetTest, test_set_volume) { VolumeControl::Get()->SetVolume(test_address, 0x20); } +TEST_F(VolumeControlValueSetTest, test_set_volume_to_previous_during_pending) { + com::android::bluetooth::flags::provider_->vcp_allow_set_same_volume_if_pending(true); + // In this test we simulate notification coming later and operations will be queued + ON_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, _, GATT_WRITE, _, _)) + .WillByDefault([](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value, + tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, void* cb_data) { + uint8_t write_rsp; + + switch (value[0]) { + case 0x04: // set abs. volume + break; + default: + break; + } + cb(conn_id, GATT_SUCCESS, handle, 0, &write_rsp, cb_data); + }); + + const std::vector<uint8_t> vol_x10({0x04, /*change_cnt*/ 0, 0x10}); + std::vector<uint8_t> ntf_value_x10({0x10, 0, 1}); + const std::vector<uint8_t> vol_x11({0x04, /*change_cnt*/ 1, 0x11}); + std::vector<uint8_t> ntf_value_x11({0x11, 0, 2}); + const std::vector<uint8_t> vol_x10_2({0x04, /*change_cnt*/ 2, 0x10}); + std::vector<uint8_t> ntf_value_x10_2({0x10, 0, 3}); + + EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10, GATT_WRITE, _, _)).Times(1); + + VolumeControl::Get()->SetVolume(test_address, 0x10); + GetNotificationEvent(0x0021, ntf_value_x10); + + EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x11, GATT_WRITE, _, _)).Times(1); + EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x0024, vol_x10_2, GATT_WRITE, _, _)) + .Times(1); + + VolumeControl::Get()->SetVolume(test_address, 0x11); + VolumeControl::Get()->SetVolume(test_address, 0x10); + GetNotificationEvent(0x0021, ntf_value_x11); + GetNotificationEvent(0x0021, ntf_value_x10_2); + + Mock::VerifyAndClearExpectations(&gatt_queue); +} + TEST_F(VolumeControlValueSetTest, test_set_volume_stress) { uint8_t n = 100; uint8_t change_cnt = 0; diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp index dc6df095ad..17d5c01905 100644 --- a/system/btcore/Android.bp +++ b/system/btcore/Android.bp @@ -24,9 +24,7 @@ cc_defaults { ], header_libs: ["libbluetooth_headers"], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], target: { host_linux: { cflags: ["-D_GNU_SOURCE"], @@ -47,9 +45,7 @@ cc_library_static { ], header_libs: ["libbluetooth_headers"], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], target: { host_linux: { cflags: ["-D_GNU_SOURCE"], @@ -80,7 +76,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "30", } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 75494590fd..498d0c1048 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -24,9 +24,7 @@ cc_library { generated_sources: ["statslog_bt.cpp"], generated_headers: ["statslog_bt.h"], export_generated_headers: ["statslog_bt.h"], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "30", shared_libs: [ "libstatssocket", @@ -64,9 +62,7 @@ cc_library_static { shared_libs: [ "libchrome", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } @@ -164,9 +160,7 @@ cc_library_static { shared_libs: [ "libbinder", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } @@ -253,9 +247,7 @@ cc_library_static { /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ "-fvisibility=default", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc index c9dd6e7b74..d15c6be99f 100644 --- a/system/btif/co/bta_av_co.cc +++ b/system/btif/co/bta_av_co.cc @@ -49,7 +49,6 @@ #include "device/include/device_iot_conf_defs.h" #include "device/include/device_iot_config.h" #include "include/hardware/bt_av.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/a2dp_codec_api.h" #include "stack/include/a2dp_constants.h" diff --git a/system/btif/include/btif_profile_storage.h b/system/btif/include/btif_profile_storage.h index 6459c45b99..d6a3688741 100644 --- a/system/btif/include/btif_profile_storage.h +++ b/system/btif/include/btif_profile_storage.h @@ -102,6 +102,9 @@ void btif_storage_set_leaudio_autoconnect(const RawAddress& addr, bool autoconne /** Store PACs information */ void btif_storage_leaudio_update_pacs_bin(const RawAddress& addr); +/** Store GMAP information */ +void btif_storage_leaudio_update_gmap_bin(const RawAddress& addr); + /** Store ASEs information */ void btif_storage_leaudio_update_ase_bin(const RawAddress& addr); diff --git a/system/btif/src/btif_a2dp_sink.cc b/system/btif/src/btif_a2dp_sink.cc index 02b92621ed..0328ba9cbc 100644 --- a/system/btif/src/btif_a2dp_sink.cc +++ b/system/btif/src/btif_a2dp_sink.cc @@ -731,6 +731,7 @@ uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { } log::verbose("+"); + /* Allocate and queue this buffer */ BT_HDR* p_msg = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(*p_msg) + p_pkt->len)); memcpy(p_msg, p_pkt, sizeof(*p_msg)); @@ -738,17 +739,18 @@ uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { memcpy(p_msg->data, p_pkt->data + p_pkt->offset, p_pkt->len); fixed_queue_enqueue(btif_a2dp_sink_cb.rx_audio_queue, p_msg); + /* If the queue is full, pop the front off to make room for the new data */ if (fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) == MAX_INPUT_A2DP_FRAME_QUEUE_SZ) { + log::verbose("Audio data buffer has reached max size. Dropping front packet"); osi_free(fixed_queue_try_dequeue(btif_a2dp_sink_cb.rx_audio_queue)); - uint8_t ret = fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue); - return ret; } - // Avoid other checks if alarm has already been initialized. + /* Check to see if we need to start decoding */ if (btif_a2dp_sink_cb.decode_alarm == nullptr && fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue) >= MAX_A2DP_DELAYED_START_FRAME_COUNT) { - log::verbose("Initiate decoding. Current focus state:{}", btif_a2dp_sink_cb.rx_focus_state); + log::verbose("Can initiate decoding, focus_state={}", btif_a2dp_sink_cb.rx_focus_state); if (btif_a2dp_sink_cb.rx_focus_state == BTIF_A2DP_SINK_FOCUS_GRANTED) { + log::info("Request to begin decoding"); btif_a2dp_sink_audio_handle_start_decoding(); } } diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc index 5a09cf2581..84bf10c390 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -64,7 +64,6 @@ #include "hardware/bluetooth.h" #include "hardware/bt_av.h" #include "include/hardware/bt_rc.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/properties.h" diff --git a/system/btif/src/btif_bqr.cc b/system/btif/src/btif_bqr.cc index 37ce06a935..eaaef220e6 100644 --- a/system/btif/src/btif_bqr.cc +++ b/system/btif/src/btif_bqr.cc @@ -725,30 +725,34 @@ static void CategorizeBqrEvent(uint8_t length, const uint8_t* p_bqr_event) { break; case QUALITY_REPORT_ID_ENERGY_MONITOR: - if (length < kEnergyMonitorParamTotalLen) { - log::fatal( - "Parameter total length: {} is abnormal. It shall be not shorter " - "than: {}", - length, kEnergyMonitorParamTotalLen); - return; - } - if (com::android::bluetooth::flags::support_bluetooth_quality_report_v6()) { - AddEnergyMonitorEventToQueue(length, p_bqr_event); + if (vendor_cap_supported_version >= kBqrVersion6_0) { + if (length < kEnergyMonitorParamTotalLen) { + log::fatal( + "Event {} Parameter total length: {} is abnormal. It shall be not shorter " + "than: {}", + quality_report_id, length, kEnergyMonitorParamTotalLen); + return; + } + + AddEnergyMonitorEventToQueue(length, p_bqr_event); + } } break; case QUALITY_REPORT_ID_RF_STATS: - if (length < kRFStatsParamTotalLen) { - log::fatal( - "Parameter total length: {} is abnormal. It shall be not shorter " - "than: {}", - length, kRFStatsParamTotalLen); - return; - } - if (com::android::bluetooth::flags::support_bluetooth_quality_report_v6()) { - AddRFStatsEventToQueue(length, p_bqr_event); + if (vendor_cap_supported_version >= kBqrVersion6_0) { + if (length < kRFStatsParamTotalLen) { + log::fatal( + "Event {} Parameter total length: {} is abnormal. It shall be not shorter " + "than: {}", + quality_report_id, length, kEnergyMonitorParamTotalLen); + return; + } + + AddRFStatsEventToQueue(length, p_bqr_event); + } } break; diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index 9164e53ef7..f0d06373b6 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -80,7 +80,7 @@ using namespace bluetooth; #if defined(TARGET_FLOSS) #define BTE_DID_CONF_FILE "/var/lib/bluetooth/bt_did.conf" #elif defined(__ANDROID__) -#define BTE_DID_CONF_FILE "/apex/com.android.btservices/etc/bluetooth/bt_did.conf" +#define BTE_DID_CONF_FILE "/apex/com.android.bt/etc/bluetooth/bt_did.conf" #else // !defined(__ANDROID__) #define BTE_DID_CONF_FILE "bt_did.conf" #endif // defined(__ANDROID__) diff --git a/system/btif/src/btif_debug_conn.cc b/system/btif/src/btif_debug_conn.cc index 935758a876..15d11cd940 100644 --- a/system/btif/src/btif_debug_conn.cc +++ b/system/btif/src/btif_debug_conn.cc @@ -21,7 +21,6 @@ #include <time.h> #include "common/time_util.h" -#include "os/logging/log_adapter.h" #include "types/raw_address.h" #define NUM_CONNECTION_EVENTS 16 diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index a130b3d134..5848ebba1c 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -74,7 +74,6 @@ #include "main/shim/le_advertising_manager.h" #include "main_thread.h" #include "metrics/bluetooth_event.h" -#include "os/logging/log_adapter.h" #include "osi/include/properties.h" #include "osi/include/stack_power_telemetry.h" #include "stack/btm/btm_dev.h" @@ -970,9 +969,8 @@ static void btif_dm_pin_req_evt(tBTA_DM_PIN_REQ* p_pin_req) { } } BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Pin request", - std::format("name:\"{}\" min16:{:c}", - PRIVATE_NAME(reinterpret_cast<char const*>(bd_name.name)), - (p_pin_req->min_16_digit) ? 'T' : 'F')); + std::format("name:\"{}\" min16:{:c}", reinterpret_cast<char const*>(bd_name.name), + p_pin_req->min_16_digit ? 'T' : 'F')); GetInterfaceToProfiles()->events->invoke_pin_request_cb(bd_addr, bd_name, cod, p_pin_req->min_16_digit); } @@ -1522,8 +1520,7 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* static bool btif_is_interesting_le_service(bluetooth::Uuid uuid) { return uuid.As16Bit() == UUID_SERVCLASS_LE_HID || uuid == UUID_HEARING_AID || uuid == UUID_VC || uuid == UUID_CSIS || uuid == UUID_LE_AUDIO || uuid == UUID_LE_MIDI || uuid == UUID_HAS || - uuid == UUID_BASS || uuid == UUID_BATTERY || - uuid == ANDROID_HEADTRACKER_SERVICE_UUID; + uuid == UUID_BASS || uuid == UUID_BATTERY || uuid == ANDROID_HEADTRACKER_SERVICE_UUID; } static bt_status_t btif_get_existing_uuids(RawAddress* bd_addr, Uuid* existing_uuids) { @@ -1859,7 +1856,7 @@ static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, co GetInterfaceToProfiles()->events->invoke_remote_device_properties_cb( status, bd_addr, properties.size(), properties.data()); log::info("Callback for read name event addr:{} name:{}", bd_addr, - PRIVATE_NAME(reinterpret_cast<char const*>(bd_name))); + reinterpret_cast<char const*>(bd_name)); if (!during_device_search) { return; @@ -1873,7 +1870,7 @@ static void btif_on_name_read(RawAddress bd_addr, tHCI_ERROR_CODE hci_status, co GetInterfaceToProfiles()->events->invoke_device_found_cb(properties.size(), properties.data()); } else { log::info("Skipping device found callback because cod is zero addr:{} name:{}", bd_addr, - PRIVATE_NAME(reinterpret_cast<char const*>(bd_name))); + reinterpret_cast<char const*>(bd_name)); } } @@ -3563,9 +3560,8 @@ static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ* p_pin_req) { cod = COD_UNCLASSIFIED; - BTM_LogHistory( - kBtmLogTagCallback, bd_addr, "PIN request", - std::format("name:'{}'", PRIVATE_NAME(reinterpret_cast<char const*>(bd_name.name)))); + BTM_LogHistory(kBtmLogTagCallback, bd_addr, "PIN request", + std::format("name:'{}'", reinterpret_cast<char const*>(bd_name.name))); GetInterfaceToProfiles()->events->invoke_pin_request_cb(bd_addr, bd_name, cod, false); } diff --git a/system/btif/src/btif_hci_vs.cc b/system/btif/src/btif_hci_vs.cc index 35b8b9cdfb..90af5cb05d 100644 --- a/system/btif/src/btif_hci_vs.cc +++ b/system/btif/src/btif_hci_vs.cc @@ -56,7 +56,7 @@ static void CommandStatusOrCompleteCallback(BluetoothHciVendorSpecificCallbacks* static void EventCallback(BluetoothHciVendorSpecificCallbacks* callbacks, VendorSpecificEventView view) { - const uint8_t aosp_reserved_codes_range[] = {0x50, 0x60}; + const uint8_t aosp_reserved_codes_range[] = {0x52, 0x60}; auto code = static_cast<uint8_t>(view.GetSubeventCode()); if (code >= aosp_reserved_codes_range[0] && code < aosp_reserved_codes_range[1]) { return; diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index bd607ea142..a8caa39452 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -63,13 +63,18 @@ #include "include/hardware/bluetooth_headset_interface.h" #include "include/hardware/bt_hf.h" #include "internal_include/bt_target.h" -#include "os/logging/log_adapter.h" #include "stack/btm/btm_sco_hfp_hal.h" #include "stack/include/bt_uuid16.h" #include "stack/include/btm_client_interface.h" #include "stack/include/btm_log_history.h" +#include "stack/include/btm_sec_api.h" #include "types/raw_address.h" +#define PRIVATE_CELL(number) \ + (number.replace(0, (number.size() > 2) ? number.size() - 2 : 0, \ + (number.size() > 2) ? number.size() - 2 : 0, '*') \ + .c_str()) + namespace { constexpr char kBtmLogTag[] = "HFP"; } @@ -467,7 +472,9 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) { log_counter_metrics_btif( android::bluetooth::CodePathCounterKeyEnum::HFP_SELF_INITIATED_AG_FAILED, 1); btif_queue_advance(); - DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(connected_bda, IOT_CONF_KEY_HFP_SLC_CONN_FAIL_COUNT); + if (btm_sec_is_a_bonded_dev(connected_bda)) { + DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(connected_bda, IOT_CONF_KEY_HFP_SLC_CONN_FAIL_COUNT); + } } break; case BTA_AG_CLOSE_EVT: { diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc index e733855233..8fc0beed06 100644 --- a/system/btif/src/btif_hh.cc +++ b/system/btif/src/btif_hh.cc @@ -455,10 +455,6 @@ static void btif_hh_start_vup_timer(const tAclLinkSpec& link_spec) { } static bthh_connection_state_t hh_get_state_on_disconnect(tAclLinkSpec& link_spec) { - if (!com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - return BTHH_CONN_STATE_ACCEPTING; - } - btif_hh_added_device_t* added_dev = btif_hh_find_added_dev(link_spec); if (added_dev != nullptr) { return added_dev->reconnect_allowed ? BTHH_CONN_STATE_ACCEPTING : BTHH_CONN_STATE_DISCONNECTED; @@ -559,55 +555,48 @@ static void hh_disable_handler(tBTA_HH_STATUS& status) { static void hh_open_handler(tBTA_HH_CONN& conn) { log::debug("link spec = {}, status = {}, handle = {}", conn.link_spec, conn.status, conn.handle); - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - // Initialize with disconnected/accepting state based on reconnection policy - bthh_connection_state_t dev_status = hh_get_state_on_disconnect(conn.link_spec); + // Initialize with disconnected/accepting state based on reconnection policy + bthh_connection_state_t dev_status = hh_get_state_on_disconnect(conn.link_spec); - // Use current state if the device instance already exists - btif_hh_device_t* p_dev = btif_hh_find_dev_by_link_spec(conn.link_spec); - if (p_dev != nullptr) { - log::debug("Device instance found: {}, state: {}", p_dev->link_spec, - bthh_connection_state_text(p_dev->dev_status)); - dev_status = p_dev->dev_status; - } + // Use current state if the device instance already exists + btif_hh_device_t* p_dev = btif_hh_find_dev_by_link_spec(conn.link_spec); + if (p_dev != nullptr) { + log::debug("Device instance found: {}, state: {}", p_dev->link_spec, + bthh_connection_state_text(p_dev->dev_status)); + dev_status = p_dev->dev_status; + } - if (std::find(btif_hh_cb.new_connection_requests.begin(), - btif_hh_cb.new_connection_requests.end(), - conn.link_spec) != btif_hh_cb.new_connection_requests.end()) { - log::verbose("Device connection was pending for: {}, status: {}", conn.link_spec, - btif_hh_status_text(btif_hh_cb.status)); - dev_status = BTHH_CONN_STATE_CONNECTING; - } + if (std::find(btif_hh_cb.new_connection_requests.begin(), + btif_hh_cb.new_connection_requests.end(), + conn.link_spec) != btif_hh_cb.new_connection_requests.end()) { + log::verbose("Device connection was pending for: {}, status: {}", conn.link_spec, + btif_hh_status_text(btif_hh_cb.status)); + dev_status = BTHH_CONN_STATE_CONNECTING; + } - if (dev_status != BTHH_CONN_STATE_ACCEPTING && dev_status != BTHH_CONN_STATE_CONNECTING) { - log::warn("Reject Incoming HID Connection, device: {}, state: {}", conn.link_spec, - bthh_connection_state_text(dev_status)); - log_counter_metrics_btif( - android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_INCOMING_CONNECTION_REJECTED, - 1); + if (dev_status != BTHH_CONN_STATE_ACCEPTING && dev_status != BTHH_CONN_STATE_CONNECTING) { + log::warn("Reject Incoming HID Connection, device: {}, state: {}", conn.link_spec, + bthh_connection_state_text(dev_status)); + log_counter_metrics_btif( + android::bluetooth::CodePathCounterKeyEnum::HIDH_COUNT_INCOMING_CONNECTION_REJECTED, 1); - if (p_dev != nullptr) { - p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED; - } + if (p_dev != nullptr) { + p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED; + } - if (!com::android::bluetooth::flags::suppress_hid_rejection_broadcast()) { - hh_connect_complete(conn, BTHH_CONN_STATE_DISCONNECTED); - return; - } - BTA_HhClose(conn.handle); + if (!com::android::bluetooth::flags::suppress_hid_rejection_broadcast()) { + hh_connect_complete(conn, BTHH_CONN_STATE_DISCONNECTED); return; } - } - - if (!com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - BTHH_STATE_UPDATE(conn.link_spec, BTHH_CONN_STATE_CONNECTING); + BTA_HhClose(conn.handle); + return; } btif_hh_cb.new_connection_requests.remove(conn.link_spec); if (conn.status != BTA_HH_OK) { btif_dm_hh_open_failed(&conn.link_spec.addrt.bda); - btif_hh_device_t* p_dev = btif_hh_find_dev_by_link_spec(conn.link_spec); + p_dev = btif_hh_find_dev_by_link_spec(conn.link_spec); if (p_dev != nullptr) { btif_hh_stop_vup_timer(p_dev->link_spec); @@ -624,7 +613,7 @@ static void hh_open_handler(tBTA_HH_CONN& conn) { return; } - btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_handle(conn.handle); + p_dev = btif_hh_find_connected_dev_by_handle(conn.handle); if (p_dev == nullptr) { /* The connect request must have come from device side and exceeded the * connected HID device number. */ @@ -819,9 +808,7 @@ static void hh_get_dscp_handler(tBTA_HH_DEV_DSCP_INFO& dscp_info) { dscp_info.descriptor.dsc_list); // Allow incoming connections - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - btif_storage_set_hid_connection_policy(p_dev->link_spec, true); - } + btif_storage_set_hid_connection_policy(p_dev->link_spec, true); ASSERTC(ret == BT_STATUS_SUCCESS, "storing hid info failed", ret); log::info("Added device {}", p_dev->link_spec); @@ -909,8 +896,7 @@ void btif_hh_load_bonded_dev(const tAclLinkSpec& link_spec_ref, tBTA_HH_ATTR_MAS uint8_t i; tAclLinkSpec link_spec = link_spec_ref; - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp() && - link_spec.transport == BT_TRANSPORT_AUTO) { + if (link_spec.transport == BT_TRANSPORT_AUTO) { log::warn("Resolving link spec {} transport to BREDR/LE", link_spec); btif_hh_transport_select(link_spec); reconnect_allowed = true; @@ -925,7 +911,7 @@ void btif_hh_load_bonded_dev(const tAclLinkSpec& link_spec_ref, tBTA_HH_ATTR_MAS } if (hh_add_device(link_spec, attr_mask, reconnect_allowed)) { - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp() && reconnect_allowed) { + if (reconnect_allowed) { BTHH_STATE_UPDATE(link_spec, BTHH_CONN_STATE_ACCEPTING); } BTA_HhAddDev(link_spec, attr_mask, sub_class, app_id, dscp_info); @@ -951,11 +937,10 @@ void btif_hh_disconnected(const RawAddress& addr, tBT_TRANSPORT transport) { if (p_dev == nullptr) { return; } - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - btif_hh_added_device_t* added_dev = btif_hh_find_added_dev(link_spec); - if (added_dev == nullptr || !added_dev->reconnect_allowed) { - return; - } + + btif_hh_added_device_t* added_dev = btif_hh_find_added_dev(link_spec); + if (added_dev == nullptr || !added_dev->reconnect_allowed) { + return; } log::debug("Rearm HoGP reconnection for {}", addr); @@ -1135,10 +1120,8 @@ bt_status_t btif_hh_connect(const tAclLinkSpec& link_spec) { } // Reset the connection policy to allow incoming reconnections - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - added_dev->reconnect_allowed = true; - btif_storage_set_hid_connection_policy(link_spec, true); - } + added_dev->reconnect_allowed = true; + btif_storage_set_hid_connection_policy(link_spec, true); } if (p_dev && p_dev->dev_status == BTHH_CONN_STATE_CONNECTED) { @@ -1660,7 +1643,7 @@ static bt_status_t disconnect(RawAddress* bd_addr, tBLE_ADDR_TYPE addr_type, return BT_STATUS_UNHANDLED; } - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp() && !reconnect_allowed) { + if (!reconnect_allowed) { log::info("Incoming reconnections disabled for device {}", link_spec); btif_hh_added_device_t* added_dev = btif_hh_find_added_dev(link_spec); if (added_dev != nullptr) { @@ -1671,27 +1654,25 @@ static bt_status_t disconnect(RawAddress* bd_addr, tBLE_ADDR_TYPE addr_type, btif_hh_device_t* p_dev = btif_hh_find_connected_dev_by_link_spec(link_spec); if (p_dev == nullptr) { - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - // Conclude the request if the device is already disconnected - p_dev = btif_hh_find_dev_by_link_spec(link_spec); - if (p_dev != nullptr && (p_dev->dev_status == BTHH_CONN_STATE_ACCEPTING || - p_dev->dev_status == BTHH_CONN_STATE_CONNECTING)) { - log::warn("Device {} already not connected, state: {}", p_dev->link_spec, - bthh_connection_state_text(p_dev->dev_status)); - p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED; - - if (com::android::bluetooth::flags::pending_hid_connection_cancellation()) { - btif_hh_cb.new_connection_requests.remove(link_spec); - } - return BT_STATUS_DONE; - } else if (com::android::bluetooth::flags::initiate_multiple_hid_connections() && - std::find(btif_hh_cb.new_connection_requests.begin(), - btif_hh_cb.new_connection_requests.end(), - link_spec) != btif_hh_cb.new_connection_requests.end()) { + // Conclude the request if the device is already disconnected + p_dev = btif_hh_find_dev_by_link_spec(link_spec); + if (p_dev != nullptr && (p_dev->dev_status == BTHH_CONN_STATE_ACCEPTING || + p_dev->dev_status == BTHH_CONN_STATE_CONNECTING)) { + log::warn("Device {} already not connected, state: {}", p_dev->link_spec, + bthh_connection_state_text(p_dev->dev_status)); + p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED; + + if (com::android::bluetooth::flags::pending_hid_connection_cancellation()) { btif_hh_cb.new_connection_requests.remove(link_spec); - log::info("Pending connection cancelled {}", link_spec); - return BT_STATUS_SUCCESS; } + return BT_STATUS_DONE; + } else if (com::android::bluetooth::flags::initiate_multiple_hid_connections() && + std::find(btif_hh_cb.new_connection_requests.begin(), + btif_hh_cb.new_connection_requests.end(), + link_spec) != btif_hh_cb.new_connection_requests.end()) { + btif_hh_cb.new_connection_requests.remove(link_spec); + log::info("Pending connection cancelled {}", link_spec); + return BT_STATUS_SUCCESS; } BTHH_LOG_UNKNOWN_LINK(link_spec); diff --git a/system/btif/src/btif_profile_storage.cc b/system/btif/src/btif_profile_storage.cc index f4ac16352c..fba4aaf5cc 100644 --- a/system/btif/src/btif_profile_storage.cc +++ b/system/btif/src/btif_profile_storage.cc @@ -145,13 +145,6 @@ bt_status_t btif_storage_add_hid_device_info(const tAclLinkSpec& link_spec, uint log::verbose("link spec: {}", link_spec.ToRedactedStringForLogging()); std::string bdstr = link_spec.addrt.bda.ToString(); - if (!com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - btif_storage_hid_device_info(bdstr, attr_mask, sub_class, app_id, vendor_id, product_id, - version, ctry_code, ssr_max_latency, ssr_min_tout, dl_len, - dsc_list); - return BT_STATUS_SUCCESS; - } - if (link_spec.transport == BT_TRANSPORT_AUTO) { log::error("Unexpected transport!"); return BT_STATUS_UNHANDLED; @@ -291,9 +284,7 @@ bt_status_t btif_storage_load_bonded_hid_info(void) { link_spec.transport = BT_TRANSPORT_AUTO; int db_version = 0; - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - btif_config_get_int(name, BTIF_STORAGE_KEY_HID_DB_VERSION, &db_version); - } + btif_config_get_int(name, BTIF_STORAGE_KEY_HID_DB_VERSION, &db_version); log::info("link spec: {}; db version: {}", link_spec, db_version); @@ -338,22 +329,20 @@ bt_status_t btif_storage_remove_hid_info(const tAclLinkSpec& link_spec) { btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT); btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_REPORT_VERSION); - if (com::android::bluetooth::flags::allow_switching_hid_and_hogp()) { - int db_version = 0; - btif_config_get_int(bdstr, BTIF_STORAGE_KEY_HID_DB_VERSION, &db_version); - if (db_version == STORAGE_HID_DB_VERSION) { - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_ATTR_MASK); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_SUB_CLASS); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_APP_ID); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_VENDOR_ID); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_PRODUCT_ID); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_VERSION); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_COUNTRY_CODE); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_DESCRIPTOR); - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_RECONNECT_ALLOWED); - } - btif_config_remove(bdstr, BTIF_STORAGE_KEY_HID_DB_VERSION); + int db_version = 0; + btif_config_get_int(bdstr, BTIF_STORAGE_KEY_HID_DB_VERSION, &db_version); + if (db_version == STORAGE_HID_DB_VERSION) { + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_ATTR_MASK); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_SUB_CLASS); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_APP_ID); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_VENDOR_ID); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_PRODUCT_ID); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_VERSION); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_COUNTRY_CODE); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_DESCRIPTOR); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HOGP_RECONNECT_ALLOWED); } + btif_config_remove(bdstr, BTIF_STORAGE_KEY_HID_DB_VERSION); return BT_STATUS_SUCCESS; } @@ -657,6 +646,21 @@ void btif_storage_leaudio_update_handles_bin(const RawAddress& addr) { } } +/** Store GMAP information */ +void btif_storage_leaudio_update_gmap_bin(const RawAddress& addr) { + std::vector<uint8_t> gmap; + + if (LeAudioClient::GetGmapForStorage(addr, gmap)) { + do_in_jni_thread(Bind( + [](const RawAddress& bd_addr, std::vector<uint8_t> gmap) { + auto bdstr = bd_addr.ToString(); + btif_config_set_bin(bdstr, BTIF_STORAGE_KEY_LEAUDIO_GMAP_BIN, gmap.data(), + gmap.size()); + }, + addr, std::move(gmap))); + } +} + /** Store PACs information */ void btif_storage_leaudio_update_pacs_bin(const RawAddress& addr) { std::vector<uint8_t> sink_pacs; @@ -805,10 +809,16 @@ void btif_storage_load_bonded_leaudio() { btif_config_get_bin(name, BTIF_STORAGE_KEY_LEAUDIO_ASES_BIN, ases.data(), &buffer_size); } + buffer_size = btif_config_get_bin_length(name, BTIF_STORAGE_KEY_LEAUDIO_GMAP_BIN); + std::vector<uint8_t> gmap(buffer_size); + if (buffer_size > 0) { + btif_config_get_bin(name, BTIF_STORAGE_KEY_LEAUDIO_GMAP_BIN, gmap.data(), &buffer_size); + } + do_in_main_thread(Bind(&LeAudioClient::AddFromStorage, bd_addr, autoconnect, sink_audio_location, source_audio_location, sink_supported_context_type, source_supported_context_type, std::move(handles), std::move(sink_pacs), - std::move(source_pacs), std::move(ases))); + std::move(source_pacs), std::move(ases), std::move(gmap))); } } @@ -817,6 +827,7 @@ void btif_storage_leaudio_clear_service_data(const RawAddress& address) { btif_config_remove(bdstr, BTIF_STORAGE_KEY_LEAUDIO_HANDLES_BIN); btif_config_remove(bdstr, BTIF_STORAGE_KEY_LEAUDIO_SINK_PACS_BIN); btif_config_remove(bdstr, BTIF_STORAGE_KEY_LEAUDIO_ASES_BIN); + btif_config_remove(bdstr, BTIF_STORAGE_KEY_LEAUDIO_GMAP_BIN); } /** Remove the Le Audio device from storage */ diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc index 72c4bdd690..1cd0f48b91 100644 --- a/system/btif/src/btif_rc.cc +++ b/system/btif/src/btif_rc.cc @@ -46,7 +46,6 @@ #include "btif_common.h" #include "btif_util.h" #include "device/include/interop.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "osi/include/allocator.h" #include "osi/include/list.h" diff --git a/system/btif/src/btif_sock_logging.cc b/system/btif/src/btif_sock_logging.cc index 338a47f2f1..acb38f7de5 100644 --- a/system/btif/src/btif_sock_logging.cc +++ b/system/btif/src/btif_sock_logging.cc @@ -25,7 +25,6 @@ #include "btif/include/btif_metrics_logging.h" #include "btif/include/btif_sock.h" -#include "os/logging/log_adapter.h" #include "types/raw_address.h" #define SOCK_LOGGER_SIZE_MAX 16 diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc index de2188c5d8..de091e8b05 100644 --- a/system/btif/src/btif_sock_rfc.cc +++ b/system/btif/src/btif_sock_rfc.cc @@ -458,7 +458,7 @@ bt_status_t btsock_rfc_connect(const RawAddress* bd_addr, const Uuid* service_uu if (!service_uuid || service_uuid->IsEmpty()) { tBTA_JV_STATUS ret = BTA_JvRfcommConnect(slot->security, slot->scn, slot->addr, rfcomm_cback, - slot->id, RfcommCfgInfo{}); + slot->id, RfcommCfgInfo{}, slot->app_uid); if (ret != tBTA_JV_STATUS::SUCCESS) { log::error("unable to initiate RFCOMM connection. status:{}, scn:{}, bd_addr:{}", bta_jv_status_text(ret), slot->scn, slot->addr); @@ -1044,7 +1044,8 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { } } // now start the rfcomm server after sdp & channel # assigned - BTA_JvRfcommStartServer(rs->security, rs->scn, MAX_RFC_SESSION, rfcomm_cback, rs->id, cfg); + BTA_JvRfcommStartServer(rs->security, rs->scn, MAX_RFC_SESSION, rfcomm_cback, rs->id, cfg, + rs->app_uid); } break; } @@ -1085,7 +1086,7 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { } // Start the rfcomm server after sdp & channel # assigned. BTA_JvRfcommStartServer(slot->security, slot->scn, MAX_RFC_SESSION, rfcomm_cback, slot->id, - cfg); + cfg, slot->app_uid); break; } @@ -1143,8 +1144,8 @@ static void handle_discovery_comp(tBTA_JV_STATUS status, int scn, uint32_t id) { } } - if (BTA_JvRfcommConnect(slot->security, scn, slot->addr, rfcomm_cback, slot->id, cfg) != - tBTA_JV_STATUS::SUCCESS) { + if (BTA_JvRfcommConnect(slot->security, scn, slot->addr, rfcomm_cback, slot->id, cfg, + slot->app_uid) != tBTA_JV_STATUS::SUCCESS) { log::warn( "BTA_JvRfcommConnect() returned BTA_JV_FAILURE for RFCOMM slot with " "id: {}", diff --git a/system/btif/test/btif_dm_test.cc b/system/btif/test/btif_dm_test.cc index 5d7595b1c5..068740472f 100644 --- a/system/btif/test/btif_dm_test.cc +++ b/system/btif/test/btif_dm_test.cc @@ -23,8 +23,9 @@ #include <memory> #include "bta/include/bta_api_data_types.h" -#include "btif/include/btif_dm.h" #include "btif/include/mock_core_callbacks.h" +#include "main/shim/entry.h" +#include "main/shim/shim.h" #include "main/shim/stack.h" #include "module.h" #include "stack/include/bt_dev_class.h" @@ -116,21 +117,47 @@ TEST_F(BtifDmWithUidTest, bta_energy_info_cb__with_uid) { ASSERT_TRUE(invoke_energy_info_cb_entered); } +// Mock implementation for GetStorage() +static bluetooth::storage::StorageModule* s_StorageModule = nullptr; +bluetooth::storage::StorageModule* bluetooth::shim::GetStorage() { return s_StorageModule; } + +bluetooth::os::Handler* bluetooth::shim::GetGdShimHandler() { return nullptr; } +bluetooth::hci::LeAdvertisingManager* bluetooth::shim::GetAdvertising() { return nullptr; } +bluetooth::hci::ControllerInterface* bluetooth::shim::GetController() { return nullptr; } +bluetooth::hci::HciInterface* bluetooth::shim::GetHciLayer() { return nullptr; } +bluetooth::hci::RemoteNameRequestModule* bluetooth::shim::GetRemoteNameRequest() { return nullptr; } +bluetooth::hci::LeScanningManager* bluetooth::shim::GetScanning() { return nullptr; } +bluetooth::hci::DistanceMeasurementManager* bluetooth::shim::GetDistanceMeasurementManager() { + return nullptr; +} +bluetooth::hal::SnoopLogger* bluetooth::shim::GetSnoopLogger() { return nullptr; } +bluetooth::lpp::LppOffloadInterface* bluetooth::shim::GetLppOffloadManager() { return nullptr; } +bluetooth::hci::AclManager* bluetooth::shim::GetAclManager() { return nullptr; } +bluetooth::metrics::CounterMetrics* bluetooth::shim::GetCounterMetrics() { return nullptr; } +bluetooth::hci::MsftExtensionManager* bluetooth::shim::GetMsftExtensionManager() { return nullptr; } + +bool bluetooth::shim::is_gd_stack_started_up() { return s_StorageModule != nullptr; } + class BtifDmWithStackTest : public BtifDmTest { protected: void SetUp() override { BtifDmTest::SetUp(); - modules_.add<bluetooth::storage::StorageModule>(); - bluetooth::shim::Stack::GetInstance()->StartModuleStack( - &modules_, - new bluetooth::os::Thread("gd_stack_thread", bluetooth::os::Thread::Priority::NORMAL)); + thread_ = new bluetooth::os::Thread("gd_stack_thread", bluetooth::os::Thread::Priority::NORMAL); + storage_module_ = new bluetooth::storage::StorageModule(new bluetooth::os::Handler(thread_)); + storage_module_->Start(); + s_StorageModule = storage_module_; } void TearDown() override { - bluetooth::shim::Stack::GetInstance()->Stop(); + storage_module_->Stop(); + s_StorageModule = nullptr; + delete storage_module_; + delete thread_; BtifDmTest::TearDown(); } - bluetooth::ModuleList modules_; + + bluetooth::os::Thread* thread_; + bluetooth::storage::StorageModule* storage_module_; }; TEST_F_WITH_FLAGS(BtifDmWithStackTest, btif_dm_search_services_evt__BTA_DM_NAME_READ_EVT) { diff --git a/system/common/Android.bp b/system/common/Android.bp index f3f2a619ca..6fe25539d9 100644 --- a/system/common/Android.bp +++ b/system/common/Android.bp @@ -49,9 +49,7 @@ cc_library_static { "libcrypto", "libcutils", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], static_libs: [ diff --git a/system/conf/interop_database.conf b/system/conf/interop_database.conf index e6521a3f14..f798e328c4 100644 --- a/system/conf/interop_database.conf +++ b/system/conf/interop_database.conf @@ -878,3 +878,8 @@ BSK10 = Name_Based # 0x03f6-0xa001 - Brydge C-Type Wireless Desktop Keyboard [INTEROP_HOGP_FORCE_MTU_EXCHANGE] 0x03f6-0xa001 = Vndr_Prdt_Based + +# Some devices claim to support HFP in EIR but do not actually support it. +[INTEROP_DISABLE_HF_PROFILE] +JBL Flip 5 = Name_Based +JBL Flip 6 = Name_Based diff --git a/system/device/Android.bp b/system/device/Android.bp index eb71e3f414..d5176640c0 100644 --- a/system/device/Android.bp +++ b/system/device/Android.bp @@ -26,9 +26,7 @@ cc_library_static { "src/esco_parameters.cc", "src/interop.cc", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], static_libs: [ @@ -97,17 +95,14 @@ cc_test { "liblog", ], static_libs: [ - "bluetooth_flags_c_lib", "libbluetooth-types", "libbluetooth_log", "libbt-platform-protos-lite", "libbtcore", "libbtdevice", "libchrome", - "libflagtest", "libgmock", "libosi", - "server_configurable_flags", ], header_libs: ["libbluetooth_headers"], } diff --git a/system/device/include/interop.h b/system/device/include/interop.h index f54ef0d715..b23900888b 100644 --- a/system/device/include/interop.h +++ b/system/device/include/interop.h @@ -362,6 +362,9 @@ typedef enum { // Some HOGP devices requires MTU exchange be part of the initial setup to function. INTEROP_HOGP_FORCE_MTU_EXCHANGE, + // Some devices claim to support HFP in EIR but does not actually support it. + INTEROP_DISABLE_HF_PROFILE, + END_OF_INTEROP_LIST } interop_feature_t; diff --git a/system/device/src/device_iot_config.cc b/system/device/src/device_iot_config.cc index 4513e6840a..f247eff0e6 100644 --- a/system/device/src/device_iot_config.cc +++ b/system/device/src/device_iot_config.cc @@ -21,7 +21,6 @@ #include "device/include/device_iot_config.h" #include <bluetooth/log.h> -#include <com_android_bluetooth_flags.h> #include <ctype.h> #include <string.h> #include <time.h> @@ -49,10 +48,6 @@ alarm_t* config_timer; using namespace bluetooth; bool device_iot_config_has_section(const std::string& section) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -60,10 +55,6 @@ bool device_iot_config_has_section(const std::string& section) { } bool device_iot_config_exist(const std::string& section, const std::string& key) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -71,10 +62,6 @@ bool device_iot_config_exist(const std::string& section, const std::string& key) } bool device_iot_config_get_int(const std::string& section, const std::string& key, int& value) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -87,10 +74,6 @@ bool device_iot_config_get_int(const std::string& section, const std::string& ke } bool device_iot_config_set_int(const std::string& section, const std::string& key, int value) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -107,10 +90,6 @@ bool device_iot_config_set_int(const std::string& section, const std::string& ke } bool device_iot_config_int_add_one(const std::string& section, const std::string& key) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); int result = 0; @@ -128,10 +107,6 @@ bool device_iot_config_int_add_one(const std::string& section, const std::string } bool device_iot_config_get_hex(const std::string& section, const std::string& key, int& value) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -159,10 +134,6 @@ bool device_iot_config_get_hex(const std::string& section, const std::string& ke bool device_iot_config_set_hex(const std::string& section, const std::string& key, int value, int byte_num) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); char value_str[32] = {0}; @@ -189,10 +160,6 @@ bool device_iot_config_set_hex(const std::string& section, const std::string& ke bool device_iot_config_set_hex_if_greater(const std::string& section, const std::string& key, int value, int byte_num) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - int stored_value = 0; bool ret = device_iot_config_get_hex(section, key, stored_value); if (ret && stored_value >= value) { @@ -204,10 +171,6 @@ bool device_iot_config_set_hex_if_greater(const std::string& section, const std: bool device_iot_config_get_str(const std::string& section, const std::string& key, char* value, int* size_bytes) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); log::assert_that(value != NULL, "assert failed: value != NULL"); log::assert_that(size_bytes != NULL, "assert failed: size_bytes != NULL"); @@ -227,10 +190,6 @@ bool device_iot_config_get_str(const std::string& section, const std::string& ke bool device_iot_config_set_str(const std::string& section, const std::string& key, const std::string& value) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -246,10 +205,6 @@ bool device_iot_config_set_str(const std::string& section, const std::string& ke bool device_iot_config_get_bin(const std::string& section, const std::string& key, uint8_t* value, size_t* length) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); log::assert_that(value != NULL, "assert failed: value != NULL"); log::assert_that(length != NULL, "assert failed: length != NULL"); @@ -293,10 +248,6 @@ bool device_iot_config_get_bin(const std::string& section, const std::string& ke } size_t device_iot_config_get_bin_length(const std::string& section, const std::string& key) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return 0; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -312,10 +263,6 @@ size_t device_iot_config_get_bin_length(const std::string& section, const std::s bool device_iot_config_set_bin(const std::string& section, const std::string& key, const uint8_t* value, size_t length) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - const char* lookup = "0123456789abcdef"; log::assert_that(config != NULL, "assert failed: config != NULL"); @@ -350,10 +297,6 @@ bool device_iot_config_set_bin(const std::string& section, const std::string& ke } bool device_iot_config_remove(const std::string& section, const std::string& key) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return false; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); std::unique_lock<std::mutex> lock(config_lock); @@ -361,10 +304,6 @@ bool device_iot_config_remove(const std::string& section, const std::string& key } void device_iot_config_flush(void) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL"); @@ -376,10 +315,6 @@ void device_iot_config_flush(void) { } bool device_iot_config_clear(void) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return true; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL"); @@ -400,10 +335,6 @@ bool device_iot_config_clear(void) { } void device_debug_iot_config_dump(int fd) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return; - } - dprintf(fd, "\nBluetooth Iot Config:\n"); dprintf(fd, " Config Source: "); diff --git a/system/device/src/device_iot_config_int.cc b/system/device/src/device_iot_config_int.cc index 33b5f8106d..fa65e13096 100644 --- a/system/device/src/device_iot_config_int.cc +++ b/system/device/src/device_iot_config_int.cc @@ -21,7 +21,6 @@ #include "device_iot_config_int.h" #include <bluetooth/log.h> -#include <com_android_bluetooth_flags.h> #include <string.h> #include <time.h> #include <unistd.h> @@ -184,10 +183,6 @@ EXPORT_SYMBOL module_t device_iot_config_module = {.name = DEVICE_IOT_CONFIG_MOD .clean_up = device_iot_config_module_clean_up}; void device_iot_config_write(uint16_t event, UNUSED_ATTR char* p_param) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL"); @@ -223,10 +218,6 @@ bool device_iot_config_has_key_value(const std::string& section, const std::stri } void device_iot_config_save_async(void) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return; - } - log::assert_that(config != NULL, "assert failed: config != NULL"); log::assert_that(config_timer != NULL, "assert failed: config_timer != NULL"); @@ -235,10 +226,6 @@ void device_iot_config_save_async(void) { } int device_iot_config_get_device_num(const config_t& conf) { - if (!com::android::bluetooth::flags::device_iot_config_logging()) { - return 0; - } - int devices = 0; for (const auto& entry : conf.sections) { diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc index 1c8798e366..354a9e1a65 100644 --- a/system/device/src/interop.cc +++ b/system/device/src/interop.cc @@ -55,7 +55,7 @@ using namespace bluetooth; #ifdef __ANDROID__ static const char* INTEROP_DYNAMIC_FILE_PATH = "/data/misc/bluedroid/interop_database_dynamic.conf"; static const char* INTEROP_STATIC_FILE_PATH = - "/apex/com.android.btservices/etc/bluetooth/interop_database.conf"; + "/apex/com.android.bt/etc/bluetooth/interop_database.conf"; #elif TARGET_FLOSS #include <base/files/file_util.h> @@ -393,6 +393,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { CASE_RETURN_STR(INTEROP_HID_PREF_CONN_ZERO_LATENCY); CASE_RETURN_STR(INTEROP_HOGP_LONG_REPORT); CASE_RETURN_STR(INTEROP_HOGP_FORCE_MTU_EXCHANGE); + CASE_RETURN_STR(INTEROP_DISABLE_HF_PROFILE); } return UNKNOWN_INTEROP_FEATURE; } diff --git a/system/device/test/device_iot_config_test.cc b/system/device/test/device_iot_config_test.cc index 4693c741d5..958a76bd7a 100644 --- a/system/device/test/device_iot_config_test.cc +++ b/system/device/test/device_iot_config_test.cc @@ -18,8 +18,6 @@ #include "device/include/device_iot_config.h" -#include <com_android_bluetooth_flags.h> -#include <flag_macros.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <sys/mman.h> @@ -34,8 +32,6 @@ #include "test/mock/mock_osi_future.h" #include "test/mock/mock_osi_properties.h" -#define TEST_BT com::android::bluetooth::flags - using namespace bluetooth; using namespace testing; @@ -132,8 +128,7 @@ protected: } }; -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_is_factory_reset, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_is_factory_reset) { bool is_factory_reset = false; config_t* config_new_return_value = NULL; config_t* config_new_empty_return_value = NULL; @@ -192,8 +187,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_no_config, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_no_config) { test::mock::osi_config::config_new.body = [&](const char* /*filename*/) { return std::unique_ptr<config_t>(nullptr); }; @@ -217,8 +211,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_original, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_original) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -268,8 +261,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_backup, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_backup) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -322,8 +314,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_new_file, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_new_file) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -367,8 +358,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_version_invalid, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_version_invalid) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -418,9 +408,8 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, - test_device_iot_config_module_init_version_new_config_new_empty_success, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, + test_device_iot_config_module_init_version_new_config_new_empty_success) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -495,9 +484,8 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, - test_device_iot_config_module_init_version_new_config_new_empty_fail, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, + test_device_iot_config_module_init_version_new_config_new_empty_fail) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -572,9 +560,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, - test_device_iot_config_module_init_original_timestamp_null, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_original_timestamp_null) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -622,8 +608,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_alarm_new_fail, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_init_alarm_new_fail) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; config_t* config_new_return_value = NULL; @@ -675,8 +660,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_init_ test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_start_up, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_start_up) { std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; @@ -699,8 +683,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_start test::mock::osi_config::config_new_empty.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_shutdown, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_shutdown) { bool return_value; std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; @@ -745,8 +728,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_shutd test::mock::osi_alarm::alarm_is_scheduled.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigModuleTest, test_device_iot_config_module_clean_up, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigModuleTest, test_device_iot_config_module_clean_up) { bool return_value; std::string enable_logging_property_get_value; std::string factory_reset_property_get_value; @@ -867,8 +849,7 @@ protected: } }; -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_sections_sort_by_entry_key, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_sections_sort_by_entry_key) { { config_t conf; device_iot_config_sections_sort_by_entry_key(conf, NULL); @@ -925,8 +906,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_sections_sort_by_e } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_has_section, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_has_section) { std::string actual_section, expected_section = "abc"; bool return_value = false; @@ -958,8 +938,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_has_section, test::mock::osi_config::config_has_section.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_exist, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_exist) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; bool return_value = false; @@ -993,8 +972,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_exist, test::mock::osi_config::config_has_key.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_has_key_value, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_has_key_value) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; std::string expected_value_str = "xyz", actual_value_str; const std::string* actual_def_value = NULL; @@ -1080,8 +1058,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_has_key_value, test::mock::osi_config::config_get_string.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_int, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_get_int) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; bool return_value = false; int int_value = 0, new_value = 0xff; @@ -1126,8 +1103,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_int, test::mock::osi_config::config_get_int.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_get_int, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_get_int) { const RawAddress peer_addr{}; std::string actual_section, actual_key, expected_section = "00:00:00:00:00:00", expected_key = "def"; @@ -1174,8 +1150,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_get_int, test::mock::osi_config::config_get_int.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_int, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_set_int) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; std::string string_return_value = "123456789"; std::string old_string_value = string_return_value; @@ -1229,8 +1204,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_int, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_int, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_set_int) { const RawAddress peer_addr{}; std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; @@ -1286,8 +1260,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_int, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_int_add_one, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_int_add_one) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; int int_value = 0, get_default_value, set_value; @@ -1393,8 +1366,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_int_add_one, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_int_add_one, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_int_add_one) { const RawAddress peer_addr{}; std::string actual_section, actual_key, expected_section = "00:00:00:00:00:00", expected_key = "def"; @@ -1501,8 +1473,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_int_add_one, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_hex, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_get_hex) { std::string actual_section, actual_key, expected_section = "00:00:00:00:00:00", expected_key = "def"; int int_value = 0; @@ -1661,8 +1632,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_hex, test::mock::osi_config::config_get_string.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_get_hex, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_get_hex) { const RawAddress peer_addr{}; std::string actual_section, actual_key, expected_section = "00:00:00:00:00:00", expected_key = "def"; @@ -1818,8 +1788,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_get_hex, test::mock::osi_config::config_get_string.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_hex, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_set_hex) { std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; std::string string_return_value; @@ -1966,8 +1935,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_hex, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_hex, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_set_hex) { const RawAddress peer_addr{}; std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; @@ -2119,8 +2087,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_hex, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_hex_if_greater, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_set_hex_if_greater) { const RawAddress peer_addr{}; std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; @@ -2205,8 +2172,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_hex_if_gr test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_str, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_get_str) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; std::string actual_value_str; const std::string* actual_def_value = NULL; @@ -2260,8 +2226,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_str, test::mock::osi_config::config_get_string.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_str, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_set_str) { std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; std::string input_value; @@ -2324,8 +2289,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_str, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_str, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_set_str) { const RawAddress peer_addr{}; std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; @@ -2389,8 +2353,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_str, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_bin, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_get_bin) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; std::string actual_value_str; const std::string* actual_def_value = NULL; @@ -2496,8 +2459,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_bin, test::mock::osi_config::config_get_string.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_bin_length, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_get_bin_length) { std::string actual_section, actual_key, expected_section = "abc", expected_key = "def"; std::string actual_value_str; const std::string* actual_def_value = NULL; @@ -2573,8 +2535,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_bin_length, test::mock::osi_config::config_get_string.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_bin, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_set_bin) { std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; std::string string_return_value; @@ -2680,8 +2641,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_bin, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_bin, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_addr_set_bin) { const RawAddress peer_addr{}; std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; @@ -2788,8 +2748,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_addr_set_bin, test::mock::osi_alarm::alarm_set.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_remove, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_remove) { std::string actual_key, expected_key = "def"; std::string actual_section, expected_section = "00:00:00:00:00:00"; bool return_value; @@ -2828,8 +2787,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_remove, test::mock::osi_config::config_remove_key.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_save_async, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_save_async) { { reset_mock_function_count_map(); @@ -2839,8 +2797,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_save_async, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_flush, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_flush) { bool return_value; test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { @@ -2876,8 +2833,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_flush, test::mock::osi_alarm::alarm_is_scheduled.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_clear, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_clear) { config_t* config_new_empty_return_value; bool config_save_return_value; @@ -2935,8 +2891,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_clear, test::mock::osi_config::config_save.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_timer_save_cb, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_timer_save_cb) { { reset_mock_function_count_map(); @@ -2946,8 +2901,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_timer_save_cb, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_modified_time, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_set_modified_time) { { reset_mock_function_count_map(); @@ -2957,8 +2911,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_set_modified_time, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_device_num, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_get_device_num) { { config_t config; auto num = device_iot_config_get_device_num(config); @@ -2980,8 +2933,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_get_device_num, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_restrict_device_num, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_restrict_device_num) { section_t section = {.name = "00:01:02:03:04:05"}; { @@ -3032,8 +2984,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_restrict_device_nu } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_compare_key, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_compare_key) { { entry_t first = { @@ -3095,8 +3046,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_compare_key, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_write, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_write) { test::mock::osi_config::config_save.body = [&](const config_t& /*config*/, const std::string& /*filename*/) -> bool { return true; }; @@ -3122,8 +3072,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_write, test::mock::osi_config::config_save.body = {}; } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_debug_iot_config_dump, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_debug_iot_config_dump) { { errno = 0; int fd = -1; @@ -3152,8 +3101,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_debug_iot_config_dump, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_is_factory_reset, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_iot_config_is_factory_reset) { bool return_value; test::mock::osi_properties::osi_property_get_bool.body = [&](const char* /*key*/, bool /*default_value*/) -> bool { return return_value; }; @@ -3169,8 +3117,7 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_iot_config_is_factory_reset, } } -TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_debug_iot_config_delete_files, - REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { +TEST_F(DeviceIotConfigTest, test_device_debug_iot_config_delete_files) { { errno = 0; int file_fd = -1; @@ -3199,248 +3146,3 @@ TEST_F_WITH_FLAGS(DeviceIotConfigTest, test_device_debug_iot_config_delete_files EXPECT_EQ(errno, ENOENT); } } -class DeviceIotConfigDisabledTest : public testing::Test { -protected: - void SetUp() override { - test::mock::osi_alarm::alarm_new.body = [&](const char* /*name*/) -> alarm_t* { - return &placeholder_alarm; - }; - - test::mock::osi_alarm::alarm_set.body = [&](alarm_t* /*alarm*/, uint64_t /*interval_ms*/, - alarm_callback_t /*cb*/, - void* /*data*/) { return; }; - - test::mock::osi_alarm::alarm_free.body = [](alarm_t* /*alarm*/) {}; - - test::mock::osi_alarm::alarm_is_scheduled.body = [&](const alarm_t* /*alarm*/) -> bool { - return false; - }; - - test::mock::osi_future::future_new_immediate.body = [&](void* /*value*/) -> future_t* { - return &placeholder_future; - }; - - test::mock::osi_config::config_new_empty.body = [&]() -> std::unique_ptr<config_t> { - return std::make_unique<config_t>(); - }; - - test::mock::osi_config::config_new.body = - [&](const char* /*filename*/) -> std::unique_ptr<config_t> { - return std::make_unique<config_t>(); - }; - - test::mock::osi_config::config_get_int.body = - [&](const config_t& /*config*/, const std::string& /*section*/, - const std::string& /*key*/, int def_value) { return def_value; }; - - test::mock::osi_config::config_set_int.body = - [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, - int /*value*/) { return; }; - - test::mock::osi_config::config_get_string.body = - [&](const config_t& /*config*/, const std::string& /*section*/, - const std::string& /*key*/, const std::string* def_value) { return def_value; }; - - test::mock::osi_config::config_set_string.body = - [&](config_t* /*config*/, const std::string& /*section*/, const std::string& /*key*/, - const std::string& /*value*/) { return; }; - - test::mock::osi_allocator::osi_free.body = [&](void* /*ptr*/) {}; - - device_iot_config_module_init(); - device_iot_config_module_start_up(); - - reset_mock_function_count_map(); - } - - void TearDown() override { - test::mock::osi_alarm::alarm_new = {}; - test::mock::osi_alarm::alarm_set = {}; - test::mock::osi_alarm::alarm_free = {}; - test::mock::osi_alarm::alarm_is_scheduled = {}; - test::mock::osi_future::future_new_immediate = {}; - test::mock::osi_properties::osi_property_get = {}; - test::mock::osi_config::config_new_empty = {}; - test::mock::osi_config::config_new = {}; - test::mock::osi_config::config_get_int = {}; - test::mock::osi_config::config_set_int = {}; - test::mock::osi_config::config_get_string = {}; - test::mock::osi_config::config_set_string = {}; - test::mock::osi_allocator::osi_free = {}; - } -}; - -TEST_F_WITH_FLAGS(DeviceIotConfigDisabledTest, test_device_iot_config_disabled, - REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(TEST_BT, device_iot_config_logging))) { - const RawAddress peer_addr{}; - std::string section, key, value_str; - int value_int{}; - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_has_section(section)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_exist(section, key)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_get_int(section, key, value_int)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_GET_INT(peer_addr, key, value_int)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_set_int(section, key, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_SET_INT(peer_addr, key, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_int_add_one(section, key)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_INT_ADD_ONE(peer_addr, key)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_get_hex(section, key, value_int)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_GET_HEX(peer_addr, key, value_int)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_set_hex(section, key, 0, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_SET_HEX(peer_addr, key, 0, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_SET_HEX_IF_GREATER(peer_addr, key, 0, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_get_str(section, key, NULL, NULL)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_set_str(section, key, value_str)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_SET_STR(peer_addr, key, value_str)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_get_bin(section, key, NULL, NULL)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_set_bin(section, key, NULL, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(DEVICE_IOT_CONFIG_ADDR_SET_BIN(peer_addr, key, NULL, 0)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_FALSE(device_iot_config_remove(section, key)); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_EQ(device_iot_config_get_bin_length(section, key), 0u); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - device_iot_config_flush(); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - EXPECT_TRUE(device_iot_config_clear()); - EXPECT_EQ(get_func_call_size(), 0); - } - - { - reset_mock_function_count_map(); - - device_debug_iot_config_dump(0); - EXPECT_EQ(get_func_call_size(), 0); - } -} diff --git a/system/embdrv/encoder_for_aptx/Android.bp b/system/embdrv/encoder_for_aptx/Android.bp index 406f8e302f..1b421089d7 100644 --- a/system/embdrv/encoder_for_aptx/Android.bp +++ b/system/embdrv/encoder_for_aptx/Android.bp @@ -42,9 +42,7 @@ cc_library_static { tidy_checks: tidy_errors, tidy_checks_as_errors: tidy_errors, min_sdk_version: "Tiramisu", - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], visibility: [ "//packages/modules/Bluetooth:__subpackages__", ], diff --git a/system/embdrv/encoder_for_aptxhd/Android.bp b/system/embdrv/encoder_for_aptxhd/Android.bp index 553d87547c..04dd120c40 100644 --- a/system/embdrv/encoder_for_aptxhd/Android.bp +++ b/system/embdrv/encoder_for_aptxhd/Android.bp @@ -42,9 +42,7 @@ cc_library_static { tidy_checks: tidy_errors, tidy_checks_as_errors: tidy_errors, min_sdk_version: "Tiramisu", - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], visibility: [ "//packages/modules/Bluetooth:__subpackages__", ], diff --git a/system/embdrv/g722/Android.bp b/system/embdrv/g722/Android.bp index 63af8f58ea..1eb2c59a1b 100644 --- a/system/embdrv/g722/Android.bp +++ b/system/embdrv/g722/Android.bp @@ -21,8 +21,6 @@ cc_library_static { "g722_encode.cc", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } diff --git a/system/embdrv/sbc/decoder/Android.bp b/system/embdrv/sbc/decoder/Android.bp index 84184fece7..2bce45cf98 100644 --- a/system/embdrv/sbc/decoder/Android.bp +++ b/system/embdrv/sbc/decoder/Android.bp @@ -35,9 +35,7 @@ cc_library_static { "srce", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } diff --git a/system/embdrv/sbc/encoder/Android.bp b/system/embdrv/sbc/encoder/Android.bp index 74fe1ec965..c583277f41 100644 --- a/system/embdrv/sbc/encoder/Android.bp +++ b/system/embdrv/sbc/encoder/Android.bp @@ -32,8 +32,6 @@ cc_library_static { "packages/modules/Bluetooth/system/stack/include", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } diff --git a/system/gd/Android.bp b/system/gd/Android.bp index aae5f1deb2..fd01e82eb2 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -177,9 +177,7 @@ cc_library_static { include_dirs: [ "packages/modules/Bluetooth/system", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "31", static_libs: [ "bluetooth_flags_c_lib", @@ -263,11 +261,11 @@ cc_test { ], static_libs: [ "bluetooth_flags_c_lib_for_test", + "libaconfig_storage_read_api_cc", "libbluetooth_log", "libchrome", "libgmock", "server_configurable_flags", - "libaconfig_storage_read_api_cc", ], shared_libs: [ "libbase", diff --git a/system/gd/AndroidTestTemplate.xml b/system/gd/AndroidTestTemplate.xml index 8332422b34..4083baac14 100644 --- a/system/gd/AndroidTestTemplate.xml +++ b/system/gd/AndroidTestTemplate.xml @@ -39,7 +39,7 @@ <!-- Only run tests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/system/gd/crypto_toolbox/Android.bp b/system/gd/crypto_toolbox/Android.bp index 05e44b7bc2..2bac8bc985 100644 --- a/system/gd/crypto_toolbox/Android.bp +++ b/system/gd/crypto_toolbox/Android.bp @@ -19,7 +19,7 @@ cc_library { name: "libbluetooth_crypto_toolbox", defaults: ["fluoride_defaults"], host_supported: true, - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "29", include_dirs: [ "packages/modules/Bluetooth/system/gd", diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc index 2e587cbfd6..326ec3e82e 100644 --- a/system/gd/hal/snoop_logger.cc +++ b/system/gd/hal/snoop_logger.cc @@ -29,6 +29,7 @@ #include <algorithm> #include <bitset> #include <chrono> +#include <filesystem> #include <sstream> #include "common/circular_buffer.h" @@ -322,6 +323,21 @@ std::string get_btsnoop_log_path(std::string log_dir, bool filtered) { std::string get_last_log_path(std::string log_file_path) { return log_file_path.append(".last"); } +#ifdef __ANDROID__ +static bool create_log_directories() { + std::filesystem::path default_path = os::ParameterProvider::SnoopLogFilePath(); + std::filesystem::path default_dir_path = default_path.parent_path(); + + if (std::filesystem::exists(default_dir_path)) { + log::info("Directory {} already exists", default_dir_path.string()); + return true; + } + + log::info("Creating directory: {}", default_dir_path.string()); + return std::filesystem::create_directories(default_dir_path); +} +#endif // __ANDROID__ + void delete_btsnoop_files(const std::string& log_path) { log::info("Deleting logs if they exist"); if (os::FileExists(log_path)) { @@ -531,6 +547,13 @@ void SnoopLogger::OpenNextSnoopLogFile() { auto last_file_path = get_last_log_path(snoop_log_path_); +#ifdef __ANDROID__ + if (com::android::bluetooth::flags::snoop_logger_recreate_logs_directory() && + !create_log_directories()) { + log::error("Could not recreate log directory"); + } +#endif // __ANDROID__ + if (os::FileExists(snoop_log_path_)) { if (!os::RenameFile(snoop_log_path_, last_file_path)) { log::error("Unabled to rename existing snoop log from \"{}\" to \"{}\"", snoop_log_path_, @@ -547,21 +570,17 @@ void SnoopLogger::OpenNextSnoopLogFile() { file_creation_time = fake_timerfd_get_clock(); #endif if (!btsnoop_ostream_.good()) { - log::error("Unable to open snoop log at \"{}\", error: \"{}\"", snoop_log_path_, + log::fatal("Unable to open snoop log at \"{}\", error: \"{}\"", snoop_log_path_, strerror(errno)); - return; } umask(prevmask); if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(&SnoopLoggerCommon::kBtSnoopFileHeader), sizeof(SnoopLoggerCommon::FileHeaderType))) { - log::error("Unable to write file header to \"{}\", error: \"{}\"", snoop_log_path_, + log::fatal("Unable to write file header to \"{}\", error: \"{}\"", snoop_log_path_, strerror(errno)); - btsnoop_ostream_.close(); - return; } if (!btsnoop_ostream_.flush()) { log::error("Failed to flush, error: \"{}\"", strerror(errno)); - return; } } @@ -725,21 +744,30 @@ uint32_t SnoopLogger::PayloadStrip(profile_type_t current_profile, uint8_t* pack uint32_t SnoopLogger::FilterProfilesHandleHfp(uint8_t* packet, uint32_t length, uint32_t totlen, uint32_t offset) { - if ((totlen - offset) > cpbr_pat_len) { - if (memcmp(&packet[offset], cpbr_pattern, cpbr_pat_len) == 0) { - length = offset + cpbr_pat_len + 1; - packet[L2CAP_PDU_LENGTH_OFFSET] = offset + cpbr_pat_len - BASIC_L2CAP_HEADER_LENGTH; - packet[L2CAP_PDU_LENGTH_OFFSET] = - offset + cpbr_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH); - return length; - } + // CPBR packet + if ((totlen - offset) > cpbr_pat_len && + memcmp(&packet[offset], cpbr_pattern, cpbr_pat_len) == 0) { + length = offset + cpbr_pat_len + 1; + packet[ACL_LENGTH_OFFSET] = offset + cpbr_pat_len - BASIC_L2CAP_HEADER_LENGTH; + packet[ACL_LENGTH_OFFSET + 1] = (offset + cpbr_pat_len - BASIC_L2CAP_HEADER_LENGTH) >> 8; - if (memcmp(&packet[offset], clcc_pattern, clcc_pat_len) == 0) { - length = offset + cpbr_pat_len + 1; - packet[L2CAP_PDU_LENGTH_OFFSET] = offset + clcc_pat_len - BASIC_L2CAP_HEADER_LENGTH; - packet[L2CAP_PDU_LENGTH_OFFSET] = - offset + clcc_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH); - } + packet[L2CAP_PDU_LENGTH_OFFSET] = + offset + cpbr_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH); + packet[L2CAP_PDU_LENGTH_OFFSET + 1] = + (offset + cpbr_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH)) >> 8; + return length; + } + // CLCC packet + if ((totlen - offset) > clcc_pat_len && + memcmp(&packet[offset], clcc_pattern, clcc_pat_len) == 0) { + length = offset + cpbr_pat_len + 1; + packet[ACL_LENGTH_OFFSET] = offset + clcc_pat_len - BASIC_L2CAP_HEADER_LENGTH; + packet[ACL_LENGTH_OFFSET + 1] = (offset + clcc_pat_len - BASIC_L2CAP_HEADER_LENGTH) >> 8; + + packet[L2CAP_PDU_LENGTH_OFFSET] = + offset + clcc_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH); + packet[L2CAP_PDU_LENGTH_OFFSET + 1] = + (offset + clcc_pat_len - (ACL_HEADER_LENGTH + BASIC_L2CAP_HEADER_LENGTH)) >> 8; } return length; @@ -1194,9 +1222,6 @@ void SnoopLogger::Capture(const HciPacket& immutable_packet, Direction direction if (packet_counter_ > max_packets_per_file_) { OpenNextSnoopLogFile(); } - if (!btsnoop_ostream_.is_open() || !btsnoop_ostream_.good()) { - return; - } if (!btsnoop_ostream_.write(reinterpret_cast<const char*>(&header), sizeof(PacketHeaderType))) { log::error("Failed to write packet header for btsnoop, error: \"{}\"", strerror(errno)); } diff --git a/system/gd/hal/snoop_logger_test.cc b/system/gd/hal/snoop_logger_test.cc index bfe81f3194..a64db3cff5 100644 --- a/system/gd/hal/snoop_logger_test.cc +++ b/system/gd/hal/snoop_logger_test.cc @@ -17,6 +17,7 @@ #include "hal/snoop_logger.h" #include <bluetooth/log.h> +#include <com_android_bluetooth_flags.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <netinet/in.h> @@ -28,6 +29,7 @@ #include "hal/snoop_logger_common.h" #include "hal/syscall_wrapper_impl.h" #include "os/fake_timer/fake_timerfd.h" +#include "os/parameter_provider.h" #include "os/system_properties.h" #include "os/utils.h" @@ -161,6 +163,7 @@ protected: } void TearDown() override { + com::android::bluetooth::flags::provider_->reset_flags(); DeleteSnoopLogFiles(); fake_timerfd_reset(); test_registry->StopAll(); @@ -389,7 +392,10 @@ TEST_F(SnoopLoggerModuleTest, delete_old_snooz_log_files) { handler->Post(bluetooth::common::BindOnce(fake_timerfd_advance, 15)); sync_handler(handler); handler->Post(bluetooth::common::BindOnce( - [](std::filesystem::path path) { ASSERT_FALSE(std::filesystem::exists(path)); }, + [](std::filesystem::path path) { + log::info("path: {}", path.string()); + ASSERT_FALSE(std::filesystem::exists(path)); + }, temp_snooz_log_)); sync_handler(handler); @@ -1392,7 +1398,7 @@ TEST_F(SnoopLoggerModuleTest, custom_socket_profiles_filtered_hfp_hf_test) { uint16_t conn_handle = 0x000b; uint16_t local_cid = 0x0043; uint16_t remote_cid = 0x3040; - uint8_t dlci = 0x06; + uint8_t dlci = 0x02; uint16_t psm = 0x0003; uint16_t profile_uuid_hfp_hf = 0x111f; bool flow = true; @@ -1400,18 +1406,22 @@ TEST_F(SnoopLoggerModuleTest, custom_socket_profiles_filtered_hfp_hf_test) { const uint16_t HEADER_SIZE = 12; size_t expected_data_size = HEADER_SIZE + strlen(clcc_pattern.c_str()); std::vector<uint8_t> kPhoneNumber = { - 0x0b, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x40, 0x30, 0x19, 0xff, 0x4f, 0x01, 0x0d, - 0x0a, 0x2b, 0x43, 0x4c, 0x43, 0x43, 0x3a, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x34, - 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x22, 0x2b, 0x39, 0x39, 0x31, 0x32, 0x33, 0x34, - 0x35, 0x36, 0x37, 0x38, 0x39, 0x22, 0x2c, 0x31, 0x34, 0x35, 0x0d, 0x0a, 0x49, + 0x0b, 0x00, 0x30, 0x00, // ACL Header (Handle: 0x000b, PB flag: 0x00, Length: 48) + 0x2c, 0x00, 0x40, 0x30, // L2CAP Header (Length: 44, CID: 0x3040) + 0x0b, 0xff, 0x4f, 0x01, // RFCOMM + // "\r\n+CLCC: 1,1,4,0,0,"+99123456789",145\r\n" + 0x0d, 0x0a, 0x2b, 0x43, 0x4c, 0x43, 0x43, 0x3a, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x34, 0x2c, + 0x30, 0x2c, 0x30, 0x2c, 0x22, 0x2b, 0x39, 0x39, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x22, 0x2c, 0x31, 0x34, 0x35, 0x0d, 0x0a, + 0x86 // RFCOMM }; std::vector<uint8_t> kExpectedPhoneNumber = { - 0x0b, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x40, 0x30, 0x19, 0xff, 0x4f, 0x01, 0x0d, - 0x0a, 0x2b, 0x43, 0x4c, 0x43, 0x43, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; + 0x0b, 0x00, 0x10, 0x00, // ACL Header (Handle: 0x000b, PB flag: 0x00, Length: 16) + 0x0c, 0x00, 0x40, 0x30, // L2CAP Header (Length: 12, CID: 0x3040) + 0x0b, 0xff, 0x4f, 0x01, // RFCOMM + // "\r\n+CLCC:" + 0x0d, 0x0a, 0x2b, 0x43, 0x4c, 0x43, 0x43, 0x3a}; // Set pbap and map filtering modes ASSERT_TRUE( @@ -1498,4 +1508,86 @@ TEST_F(SnoopLoggerModuleTest, custom_socket_profiles_filtered_hfp_hf_test) { test_registry->StopAll(); close(socket_fd); } + +#ifdef __ANDROID__ +TEST_F(SnoopLoggerModuleTest, recreate_log_directory_when_enabled_test) { + com::android::bluetooth::flags::provider_->snoop_logger_recreate_logs_directory(true); + // Actual test + const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); + const std::filesystem::path os_btsnoop_file_path_ = os::ParameterProvider::SnoopLogFilePath(); + std::filesystem::path temp_dir_path_ = os_btsnoop_file_path_.parent_path(); + + const std::filesystem::path temp_log_btsnoop_file_ = + temp_dir_path_ / (std::string(test_info->name()) + "_btsnoop_hci.log"); + const std::filesystem::path temp_log_btsnooz_file_ = + temp_dir_path_ / (std::string(test_info->name()) + "_btsnooz_hci.log"); + + if (std::filesystem::exists(temp_dir_path_)) { + std::filesystem::remove_all(temp_dir_path_); + } + + ASSERT_FALSE(std::filesystem::exists(temp_dir_path_)); + + auto* snoop_logger = new TestSnoopLoggerModule(temp_log_btsnoop_file_.string(), + temp_log_btsnooz_file_.string(), 10, + SnoopLogger::kBtSnoopLogModeFull, false, false); + test_registry->InjectTestModule(&SnoopLogger::Factory, snoop_logger); + + ASSERT_TRUE(std::filesystem::exists(temp_dir_path_)); + + test_registry->StopAll(); + + // btsnoop file should exist + ASSERT_TRUE(std::filesystem::exists(temp_log_btsnoop_file_)); + // btsnooz file should be removed as snoop_log_persists is false + ASSERT_FALSE(std::filesystem::exists(temp_log_btsnooz_file_)); + // remove after test + if (std::filesystem::exists(temp_dir_path_)) { + std::filesystem::remove_all(temp_dir_path_); + } +} + +TEST_F(SnoopLoggerModuleTest, recreate_log_directory_when_filtered_test) { + com::android::bluetooth::flags::provider_->snoop_logger_recreate_logs_directory(true); + // Actual test + const testing::TestInfo* const test_info = testing::UnitTest::GetInstance()->current_test_info(); + const std::filesystem::path os_btsnoop_file_path_ = os::ParameterProvider::SnoopLogFilePath(); + std::filesystem::path temp_dir_path_ = os_btsnoop_file_path_.parent_path(); + + const std::filesystem::path temp_log_btsnoop_file_ = + temp_dir_path_ / (std::string(test_info->name()) + "_btsnoop_hci.log"); + const std::filesystem::path temp_log_btsnooz_file_ = + temp_dir_path_ / (std::string(test_info->name()) + "_btsnooz_hci.log"); + + if (std::filesystem::exists(temp_dir_path_)) { + std::filesystem::remove_all(temp_dir_path_); + } + + ASSERT_FALSE(std::filesystem::exists(temp_dir_path_)); + + auto* snoop_logger = new TestSnoopLoggerModule( + temp_log_btsnoop_file_.string(), temp_log_btsnooz_file_.string(), 10, + SnoopLogger::kBtSnoopLogModeFiltered, false, false); + test_registry->InjectTestModule(&SnoopLogger::Factory, snoop_logger); + + ASSERT_TRUE(std::filesystem::exists(temp_dir_path_)); + + test_registry->StopAll(); + + const std::filesystem::path temp_log_btsnoop_filtered_file_ = + temp_dir_path_ / (std::string(test_info->name()) + "_btsnoop_hci.log.filtered"); + const std::filesystem::path temp_log_btsnooz_filtered_file_ = + temp_dir_path_ / (std::string(test_info->name()) + "_btsnooz_hci.log.filtered"); + + // btsnoop file should exist + ASSERT_TRUE(std::filesystem::exists(temp_log_btsnoop_filtered_file_)); + // btsnooz file should be removed as snoop_log_persists is false + ASSERT_FALSE(std::filesystem::exists(temp_log_btsnooz_filtered_file_)); + // remove after test + if (std::filesystem::exists(temp_dir_path_)) { + std::filesystem::remove_all(temp_dir_path_); + } +} +#endif // __ANDROID__ + } // namespace testing diff --git a/system/gd/hci/address.h b/system/gd/hci/address.h index 10a817cc1c..17c2fce6b4 100644 --- a/system/gd/hci/address.h +++ b/system/gd/hci/address.h @@ -25,7 +25,6 @@ #include <ostream> #include <string> -#include "os/logging/log_adapter.h" #include "packet/custom_field_fixed_size_interface.h" #include "storage/serializable.h" diff --git a/system/gd/hci/address_with_type.h b/system/gd/hci/address_with_type.h index 350b88df75..26c35e814d 100644 --- a/system/gd/hci/address_with_type.h +++ b/system/gd/hci/address_with_type.h @@ -26,7 +26,6 @@ #include "hci/address.h" #include "hci/hci_packets.h" #include "hci/octets.h" -#include "os/logging/log_adapter.h" namespace bluetooth { namespace hci { diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index 1311815633..74ba01e075 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -294,6 +294,16 @@ struct HciLayer::impl { } void on_hci_timeout(OpCode op_code) { +#ifdef TARGET_FLOSS + log::warn("Ignoring the timeouted HCI command {}.", OpCodeText(op_code)); + // Terminate the process to trigger controller reset, also mark the controller + // is broken to prevent further error while terminating. + auto hal = module_.GetDependency<hal::HciHal>(); + hal->markControllerBroken(); + kill(getpid(), SIGTERM); + return; +#endif + common::StopWatch::DumpStopWatchLog(); log::error("Timed out waiting for {} for {}ms", OpCodeText(op_code), getHciTimeoutMs().count()); @@ -305,16 +315,6 @@ struct HciLayer::impl { command_credits_ = 1; waiting_command_ = OpCode::NONE; -#ifdef TARGET_FLOSS - log::warn("Ignoring the timeouted HCI command {}.", OpCodeText(op_code)); - // Terminate the process to trigger controller reset, also mark the controller - // is broken to prevent further error while terminating. - auto hal = module_.GetDependency<hal::HciHal>(); - hal->markControllerBroken(); - kill(getpid(), SIGTERM); - return; -#endif - // Ignore the response, since we don't know what might come back. enqueue_command(ControllerDebugInfoBuilder::Create(), module_.GetHandler()->BindOnce([](CommandCompleteView) {})); diff --git a/system/gd/module.h b/system/gd/module.h index e708035a77..858d4cd070 100644 --- a/system/gd/module.h +++ b/system/gd/module.h @@ -81,9 +81,12 @@ class Module { friend TestModuleRegistry; public: + Module() = default; virtual ~Module() = default; protected: + Module(os::Handler* handler) : handler_(handler) {} + // Populate the provided list with modules that must start before yours virtual void ListDependencies(ModuleList* list) const = 0; diff --git a/system/gd/os/logging/log_adapter.h b/system/gd/os/logging/log_adapter.h deleted file mode 100644 index 0da4866fec..0000000000 --- a/system/gd/os/logging/log_adapter.h +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * - * Copyright 2022 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#pragma once - -#include <string> - -#define PRIVATE_CELL(number) \ - (number.replace(0, (number.size() > 2) ? number.size() - 2 : 0, \ - (number.size() > 2) ? number.size() - 2 : 0, '*') \ - .c_str()) - -#define PRIVATE_NAME(name) (name) diff --git a/system/gd/proto/Android.bp b/system/gd/proto/Android.bp index 6136cf84f6..1f7e72687f 100644 --- a/system/gd/proto/Android.bp +++ b/system/gd/proto/Android.bp @@ -16,9 +16,7 @@ java_library_static { srcs: [ "bluetooth/metrics/bluetooth.proto", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "30", sdk_version: "current", } @@ -41,8 +39,6 @@ cc_library_static { srcs: [ "bluetooth/metrics/bluetooth.proto", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "30", } diff --git a/system/gd/rust/common/Android.bp b/system/gd/rust/common/Android.bp index a1e8c4a977..26b724c900 100644 --- a/system/gd/rust/common/Android.bp +++ b/system/gd/rust/common/Android.bp @@ -35,9 +35,7 @@ rust_library { ], }, }, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", } diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs index 59645ab0dc..e87d3d9086 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_media.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs @@ -15,7 +15,7 @@ use bt_topshim::profiles::avrcp::{ use bt_topshim::profiles::csis::{ BtCsisConnectionState, CsisClient, CsisClientCallbacks, CsisClientCallbacksDispatcher, }; -use bt_topshim::profiles::hfp::interop_insert_call_when_sco_start; +use bt_topshim::profiles::hfp::{interop_disable_hf_profile, interop_insert_call_when_sco_start}; use bt_topshim::profiles::hfp::{ BthfAudioState, BthfConnectionState, CallHoldCommand, CallInfo, CallState, EscoCodingFormat, Hfp, HfpCallbacks, HfpCallbacksDispatcher, HfpCodecBitId, HfpCodecFormat, HfpCodecId, @@ -2553,15 +2553,23 @@ impl BluetoothMedia { } fn adapter_get_classic_audio_profiles(&self, addr: RawAddress) -> HashSet<Profile> { + let name = self.adapter_get_remote_name(addr); let device = BluetoothDevice::new(addr, "".to_string()); - self.adapter + let mut profiles: HashSet<_> = self + .adapter .lock() .unwrap() .get_remote_uuids(device) .into_iter() .filter_map(|u| UuidHelper::is_known_profile(&u)) .filter(|u| MEDIA_CLASSIC_AUDIO_PROFILES.contains(u)) - .collect() + .collect(); + + if interop_disable_hf_profile(name) { + profiles.remove(&Profile::Hfp); + } + + profiles } pub fn get_hfp_connection_state(&self) -> ProfileConnectionState { diff --git a/system/gd/rust/topshim/hfp/hfp_shim.cc b/system/gd/rust/topshim/hfp/hfp_shim.cc index 02eba51274..02909b391d 100644 --- a/system/gd/rust/topshim/hfp/hfp_shim.cc +++ b/system/gd/rust/topshim/hfp/hfp_shim.cc @@ -383,6 +383,10 @@ bool interop_insert_call_when_sco_start(RawAddress addr) { return interop_match_addr(interop_feature_t::INTEROP_INSERT_CALL_WHEN_SCO_START, &addr); } +bool interop_disable_hf_profile(const char* name) { + return interop_match_name(interop_feature_t::INTEROP_DISABLE_HF_PROFILE, name); +} + } // namespace rust } // namespace topshim } // namespace bluetooth diff --git a/system/gd/rust/topshim/hfp/hfp_shim.h b/system/gd/rust/topshim/hfp/hfp_shim.h index 0b769e98ce..5503676634 100644 --- a/system/gd/rust/topshim/hfp/hfp_shim.h +++ b/system/gd/rust/topshim/hfp/hfp_shim.h @@ -59,6 +59,7 @@ private: std::unique_ptr<HfpIntf> GetHfpProfile(const unsigned char* btif); bool interop_insert_call_when_sco_start(RawAddress addr); +bool interop_disable_hf_profile(const char* name); } // namespace rust } // namespace topshim diff --git a/system/gd/rust/topshim/src/profiles/hfp.rs b/system/gd/rust/topshim/src/profiles/hfp.rs index f2da4b2fd8..b31926bb19 100644 --- a/system/gd/rust/topshim/src/profiles/hfp.rs +++ b/system/gd/rust/topshim/src/profiles/hfp.rs @@ -192,6 +192,7 @@ pub mod ffi { unsafe fn GetHfpProfile(btif: *const u8) -> UniquePtr<HfpIntf>; unsafe fn interop_insert_call_when_sco_start(bt_addr: RawAddress) -> bool; + unsafe fn interop_disable_hf_profile(name: *const c_char) -> bool; fn init(self: Pin<&mut HfpIntf>) -> i32; fn connect(self: Pin<&mut HfpIntf>, bt_addr: RawAddress) -> u32; fn connect_audio( @@ -265,6 +266,12 @@ pub fn interop_insert_call_when_sco_start(bt_addr: RawAddress) -> bool { unsafe { return ffi::interop_insert_call_when_sco_start(bt_addr) } } +pub fn interop_disable_hf_profile(name: String) -> bool { + let c_name = std::ffi::CString::new(name).unwrap(); + // Call an unsafe function in c++. This is necessary for bridge C++ interop API with floss(rust). + unsafe { return ffi::interop_disable_hf_profile(c_name.as_ptr()) } +} + pub type TelephonyDeviceStatus = ffi::TelephonyDeviceStatus; impl TelephonyDeviceStatus { diff --git a/system/gd/storage/config_keys.h b/system/gd/storage/config_keys.h index c3e6573c78..4629a494ba 100644 --- a/system/gd/storage/config_keys.h +++ b/system/gd/storage/config_keys.h @@ -99,6 +99,7 @@ #define BTIF_STORAGE_KEY_LEAUDIO_SOURCE_AUDIOLOCATION "SourceAudioLocation" #define BTIF_STORAGE_KEY_LEAUDIO_SOURCE_PACS_BIN "SourcePacsBin" #define BTIF_STORAGE_KEY_LEAUDIO_SOURCE_SUPPORTED_CONTEXT_TYPE "SourceSupportedContextType" +#define BTIF_STORAGE_KEY_LEAUDIO_GMAP_BIN "LeAudioGmap" #define BTIF_STORAGE_KEY_LINK_KEY "LinkKey" #define BTIF_STORAGE_KEY_LINK_KEY_TYPE "LinkKeyType" #define BTIF_STORAGE_KEY_LOCAL_IO_CAPS "LocalIOCaps" diff --git a/system/gd/storage/storage_module.cc b/system/gd/storage/storage_module.cc index ce5a89c6f7..0a7c9a7ef1 100644 --- a/system/gd/storage/storage_module.cc +++ b/system/gd/storage/storage_module.cc @@ -63,11 +63,20 @@ const std::string StorageModule::kTimeCreatedFormat = "%Y-%m-%d %H:%M:%S"; const std::string StorageModule::kAdapterSection = BTIF_STORAGE_SECTION_ADAPTER; -StorageModule::StorageModule(std::string config_file_path, +StorageModule::StorageModule() + : StorageModule(nullptr, os::ParameterProvider::ConfigFilePath(), kDefaultConfigSaveDelay, + kDefaultTempDeviceCapacity, false, false) {} + +StorageModule::StorageModule(os::Handler* handler) + : StorageModule(handler, os::ParameterProvider::ConfigFilePath(), kDefaultConfigSaveDelay, + kDefaultTempDeviceCapacity, false, false) {} + +StorageModule::StorageModule(os::Handler* handler, std::string config_file_path, std::chrono::milliseconds config_save_delay, size_t temp_devices_capacity, bool is_restricted_mode, bool is_single_user_mode) - : config_file_path_(std::move(config_file_path)), + : Module(handler), + config_file_path_(std::move(config_file_path)), config_save_delay_(config_save_delay), temp_devices_capacity_(temp_devices_capacity), is_restricted_mode_(is_restricted_mode), @@ -84,10 +93,7 @@ StorageModule::~StorageModule() { pimpl_.reset(); } -const ModuleFactory StorageModule::Factory = ModuleFactory([]() { - return new StorageModule(os::ParameterProvider::ConfigFilePath(), kDefaultConfigSaveDelay, - kDefaultTempDeviceCapacity, false, false); -}); +const ModuleFactory StorageModule::Factory = ModuleFactory([]() { return new StorageModule(); }); struct StorageModule::impl { explicit impl(Handler* handler, ConfigCache cache, size_t in_memory_cache_size_limit) @@ -144,9 +150,7 @@ void StorageModule::Clear() { pimpl_->cache_.Clear(); } -void StorageModule::ListDependencies(ModuleList* list) const { - list->add<metrics::CounterMetrics>(); -} +void StorageModule::ListDependencies(ModuleList* /*list*/) const {} void StorageModule::Start() { std::lock_guard<std::recursive_mutex> lock(mutex_); diff --git a/system/gd/storage/storage_module.h b/system/gd/storage/storage_module.h index 12f5750196..b94251a0dc 100644 --- a/system/gd/storage/storage_module.h +++ b/system/gd/storage/storage_module.h @@ -55,12 +55,17 @@ public: static const std::string kAdapterSection; + StorageModule(); + StorageModule(os::Handler*); StorageModule(const StorageModule&) = delete; StorageModule& operator=(const StorageModule&) = delete; ~StorageModule(); static const ModuleFactory Factory; + void Start() override; + void Stop() override; + // Methods to access the storage layer via Device abstraction // - Devices will be lazily created when methods below are called. Hence, no std::optional<> nor // nullptr is used in @@ -121,8 +126,6 @@ public: protected: void ListDependencies(ModuleList* list) const override; - void Start() override; - void Stop() override; std::string ToString() const override; friend shim::BtifConfigInterface; @@ -147,8 +150,9 @@ protected: // - temp_devices_capacity is the number of temporary, typically unpaired devices to hold in a // memory based LRU // - is_restricted_mode and is_single_user_mode are flags from upper layer - StorageModule(std::string config_file_path, std::chrono::milliseconds config_save_delay, - size_t temp_devices_capacity, bool is_restricted_mode, bool is_single_user_mode); + StorageModule(os::Handler* handler, std::string config_file_path, + std::chrono::milliseconds config_save_delay, size_t temp_devices_capacity, + bool is_restricted_mode, bool is_single_user_mode); bool HasSection(const std::string& section) const; bool HasProperty(const std::string& section, const std::string& property) const; diff --git a/system/gd/storage/storage_module_test.cc b/system/gd/storage/storage_module_test.cc index 2f600944ae..e58c210609 100644 --- a/system/gd/storage/storage_module_test.cc +++ b/system/gd/storage/storage_module_test.cc @@ -53,8 +53,8 @@ class TestStorageModule : public StorageModule { public: TestStorageModule(std::string config_file_path, std::chrono::milliseconds config_save_delay, bool is_restricted_mode, bool is_single_user_mode) - : StorageModule(std::move(config_file_path), config_save_delay, kTestTempDevicesCapacity, - is_restricted_mode, is_single_user_mode) {} + : StorageModule(nullptr, std::move(config_file_path), config_save_delay, + kTestTempDevicesCapacity, is_restricted_mode, is_single_user_mode) {} ConfigCache* GetMemoryOnlyConfigCachePublic() { return StorageModule::GetMemoryOnlyConfigCache(); diff --git a/system/hci/Android.bp b/system/hci/Android.bp index e4e0106606..1f0a51435a 100644 --- a/system/hci/Android.bp +++ b/system/hci/Android.bp @@ -26,9 +26,7 @@ cc_library_static { "packages/modules/Bluetooth/system/stack/include", "system/libhwbinder/include", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], diff --git a/system/include/Android.bp b/system/include/Android.bp index 2482effbf3..c7cec2e726 100644 --- a/system/include/Android.bp +++ b/system/include/Android.bp @@ -22,7 +22,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "30", } @@ -49,7 +49,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "30", } diff --git a/system/internal_include/Android.bp b/system/internal_include/Android.bp index 7d66847ebf..06a56b06fa 100644 --- a/system/internal_include/Android.bp +++ b/system/internal_include/Android.bp @@ -14,7 +14,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "30", } diff --git a/system/internal_include/bt_trace.h b/system/internal_include/bt_trace.h index 5bd07ca0e0..3b8b7166b4 100644 --- a/system/internal_include/bt_trace.h +++ b/system/internal_include/bt_trace.h @@ -29,8 +29,6 @@ #include <sstream> #include <type_traits> -#include "os/logging/log_adapter.h" - /* Prints integral parameter x as hex string, with '0' fill */ template <typename T> std::string loghex(T x) { diff --git a/system/log/Android.bp b/system/log/Android.bp index ebfd81d1fb..649a039aff 100644 --- a/system/log/Android.bp +++ b/system/log/Android.bp @@ -2,9 +2,7 @@ cc_library { name: "libbluetooth_log", host_supported: true, min_sdk_version: "33", - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], export_include_dirs: [ "include", ], diff --git a/system/main/Android.bp b/system/main/Android.bp index 5272905831..15b1351bc3 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -41,9 +41,7 @@ cc_library_static { "packages/modules/Bluetooth/system/udrv/include", "system/security/keystore/include", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", static_libs: [ @@ -102,9 +100,7 @@ cc_library { sanitize: { scs: true, }, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "30", } diff --git a/system/main/shim/entry.cc b/system/main/shim/entry.cc index ff0014b481..9fe8e8bd55 100644 --- a/system/main/shim/entry.cc +++ b/system/main/shim/entry.cc @@ -27,6 +27,7 @@ #include "hci/msft.h" #include "hci/remote_name_request.h" #include "lpp/lpp_offload_manager.h" +#include "main/shim/shim.h" #include "main/shim/stack.h" #include "metrics/counter_metrics.h" #include "os/handler.h" @@ -79,5 +80,7 @@ hci::MsftExtensionManager* GetMsftExtensionManager() { return Stack::GetInstance()->GetInstance<hci::MsftExtensionManager>(); } +bool is_gd_stack_started_up() { return Stack::GetInstance()->IsRunning(); } + } // namespace shim } // namespace bluetooth diff --git a/system/main/shim/shim.cc b/system/main/shim/shim.cc index 69c70cd9ba..81bd0b6bf3 100644 --- a/system/main/shim/shim.cc +++ b/system/main/shim/shim.cc @@ -54,7 +54,3 @@ EXPORT_SYMBOL extern const module_t gd_shim_module = {.name = GD_SHIM_MODULE, .shut_down = GeneralShutDown, .clean_up = kUnusedModuleApi, .dependencies = {kUnusedModuleDependencies}}; - -bool bluetooth::shim::is_gd_stack_started_up() { - return bluetooth::shim::Stack::GetInstance()->IsRunning(); -} diff --git a/system/main/shim/stack.cc b/system/main/shim/stack.cc index 6da9117ae4..09455bb47c 100644 --- a/system/main/shim/stack.cc +++ b/system/main/shim/stack.cc @@ -104,7 +104,28 @@ void Stack::StartEverything() { modules.add<hci::DistanceMeasurementManager>(); stack_thread_ = new os::Thread("gd_stack_thread", os::Thread::Priority::REAL_TIME); - StartUp(&modules, stack_thread_); + + management_thread_ = new Thread("management_thread", Thread::Priority::NORMAL); + management_handler_ = new Handler(management_thread_); + + WakelockManager::Get().Acquire(); + + std::promise<void> promise; + auto future = promise.get_future(); + management_handler_->Post(common::BindOnce(&Stack::handle_start_up, common::Unretained(this), + &modules, std::move(promise))); + + auto init_status = future.wait_for( + std::chrono::milliseconds(get_gd_stack_timeout_ms(/* is_start = */ true))); + + WakelockManager::Get().Release(); + + log::info("init_status == {}", int(init_status)); + + log::assert_that(init_status == std::future_status::ready, "Can't start stack, last instance: {}", + registry_.last_instance_); + + log::info("init complete"); stack_handler_ = new os::Handler(stack_thread_); @@ -127,19 +148,6 @@ void Stack::StartEverything() { bluetooth::shim::init_distance_measurement_manager(); } -void Stack::StartModuleStack(const ModuleList* modules, const os::Thread* thread) { - std::lock_guard<std::recursive_mutex> lock(mutex_); - log::assert_that(!is_running_, "Gd stack already running"); - stack_thread_ = const_cast<os::Thread*>(thread); - log::info("Starting Gd stack"); - - StartUp(const_cast<ModuleList*>(modules), stack_thread_); - stack_handler_ = new os::Handler(stack_thread_); - - num_modules_ = modules->NumModules(); - is_running_ = true; -} - void Stack::Stop() { std::lock_guard<std::recursive_mutex> lock(mutex_); bluetooth::shim::hci_on_shutting_down(); @@ -222,32 +230,8 @@ void Stack::Dump(int fd, std::promise<void> promise) const { } } -void Stack::StartUp(ModuleList* modules, Thread* stack_thread) { - management_thread_ = new Thread("management_thread", Thread::Priority::NORMAL); - management_handler_ = new Handler(management_thread_); - - WakelockManager::Get().Acquire(); - - std::promise<void> promise; - auto future = promise.get_future(); - management_handler_->Post(common::BindOnce(&Stack::handle_start_up, common::Unretained(this), - modules, stack_thread, std::move(promise))); - - auto init_status = future.wait_for( - std::chrono::milliseconds(get_gd_stack_timeout_ms(/* is_start = */ true))); - - WakelockManager::Get().Release(); - - log::info("init_status == {}", int(init_status)); - - log::assert_that(init_status == std::future_status::ready, "Can't start stack, last instance: {}", - registry_.last_instance_); - - log::info("init complete"); -} - -void Stack::handle_start_up(ModuleList* modules, Thread* stack_thread, std::promise<void> promise) { - registry_.Start(modules, stack_thread); +void Stack::handle_start_up(ModuleList* modules, std::promise<void> promise) { + registry_.Start(modules, stack_thread_); promise.set_value(); } diff --git a/system/main/shim/stack.h b/system/main/shim/stack.h index 0dfd3fe3ab..c79a9de21b 100644 --- a/system/main/shim/stack.h +++ b/system/main/shim/stack.h @@ -58,16 +58,10 @@ public: } Acl* GetAcl(); - os::Handler* GetHandler(); void Dump(int fd, std::promise<void> promise) const; - // Start the list of modules with the given stack manager thread - void StartModuleStack(const ModuleList* modules, const os::Thread* thread); - - size_t NumModules() const { return num_modules_; } - private: struct impl; std::shared_ptr<impl> pimpl_; @@ -76,15 +70,12 @@ private: bool is_running_ = false; os::Thread* stack_thread_ = nullptr; os::Handler* stack_handler_ = nullptr; - size_t num_modules_{0}; - - void StartUp(ModuleList* modules, os::Thread* stack_thread); os::Thread* management_thread_ = nullptr; os::Handler* management_handler_ = nullptr; ModuleRegistry registry_; - void handle_start_up(ModuleList* modules, os::Thread* stack_thread, std::promise<void> promise); + void handle_start_up(ModuleList* modules, std::promise<void> promise); void handle_shut_down(std::promise<void> promise); static std::chrono::milliseconds get_gd_stack_timeout_ms(bool is_start); }; diff --git a/system/main/stack_config.cc b/system/main/stack_config.cc index 9b04e7f16c..20db9be13d 100644 --- a/system/main/stack_config.cc +++ b/system/main/stack_config.cc @@ -60,7 +60,7 @@ static future_t* init() { #if defined(TARGET_FLOSS) const char* path = "/etc/bluetooth/bt_stack.conf"; #elif defined(__ANDROID__) - const char* path = "/apex/com.android.btservices/etc/bluetooth/bt_stack.conf"; + const char* path = "/apex/com.android.bt/etc/bluetooth/bt_stack.conf"; #else // !defined(__ANDROID__) const char* path = "bt_stack.conf"; #endif // defined(__ANDROID__) diff --git a/system/osi/Android.bp b/system/osi/Android.bp index 4806d61985..23055416f2 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -83,9 +83,7 @@ cc_library_static { "-DLIB_OSI_INTERNAL", ], min_sdk_version: "Tiramisu", - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], header_libs: ["libbluetooth_headers"], static_libs: [ "bluetooth_flags_c_lib", diff --git a/system/osi/src/stack_power_telemetry.cc b/system/osi/src/stack_power_telemetry.cc index 18199bcd18..52d5bfcd2a 100644 --- a/system/osi/src/stack_power_telemetry.cc +++ b/system/osi/src/stack_power_telemetry.cc @@ -28,7 +28,6 @@ #include <map> #include <mutex> -#include "os/logging/log_adapter.h" #include "osi/include/properties.h" #include "stack/include/acl_api_types.h" #include "stack/include/bt_psm_types.h" diff --git a/system/packet/Android.bp b/system/packet/Android.bp index d3ba6dfd71..05c2c8cc5b 100644 --- a/system/packet/Android.bp +++ b/system/packet/Android.bp @@ -20,9 +20,7 @@ cc_library_static { "lib-bt-packets-base", "libbluetooth_log", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "30", } diff --git a/system/packet/avrcp/Android.bp b/system/packet/avrcp/Android.bp index 1808112072..ee51ed340a 100644 --- a/system/packet/avrcp/Android.bp +++ b/system/packet/avrcp/Android.bp @@ -48,8 +48,6 @@ cc_library_static { "libbluetooth_log", "libchrome", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "30", } diff --git a/system/packet/base/Android.bp b/system/packet/base/Android.bp index 732d597c34..f81a511374 100644 --- a/system/packet/base/Android.bp +++ b/system/packet/base/Android.bp @@ -18,9 +18,7 @@ cc_library_static { "packet.cc", "packet_builder.cc", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "30", shared_libs: [ "libbase", diff --git a/system/pdl/hci/Android.bp b/system/pdl/hci/Android.bp index 354d500300..832598aaff 100644 --- a/system/pdl/hci/Android.bp +++ b/system/pdl/hci/Android.bp @@ -19,9 +19,7 @@ cc_library_headers { "BluetoothGeneratedPacketsHci_h", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } @@ -48,9 +46,7 @@ cc_library_static { "//hardware/interfaces/bluetooth/aidl/vts", "//packages/modules/Bluetooth/system:__subpackages__", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } diff --git a/system/pdl/hci/include/hci/address.h b/system/pdl/hci/include/hci/address.h index 7694689bf2..0d258ed0ff 100644 --- a/system/pdl/hci/include/hci/address.h +++ b/system/pdl/hci/include/hci/address.h @@ -25,7 +25,6 @@ #include <ostream> #include <string> -#include "os/logging/log_adapter.h" #include "packet/custom_field_fixed_size_interface.h" #include "storage/serializable.h" diff --git a/system/pdl/l2cap/Android.bp b/system/pdl/l2cap/Android.bp index d55935995c..bbd499612e 100644 --- a/system/pdl/l2cap/Android.bp +++ b/system/pdl/l2cap/Android.bp @@ -15,9 +15,7 @@ cc_library_headers { "BluetoothGeneratedPacketsL2cap_h", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } @@ -30,8 +28,6 @@ cc_library_static { "libbluetooth_l2cap_pdl_header", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } diff --git a/system/pdl/ras/Android.bp b/system/pdl/ras/Android.bp index d54d753b77..84e516c64f 100644 --- a/system/pdl/ras/Android.bp +++ b/system/pdl/ras/Android.bp @@ -15,9 +15,7 @@ cc_library_headers { "BluetoothGeneratedPacketsRas_h", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } @@ -30,8 +28,6 @@ cc_library_static { "libbluetooth_ras_pdl_header", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } diff --git a/system/pdl/security/Android.bp b/system/pdl/security/Android.bp index ebd5a3d8db..fbbc2b7339 100644 --- a/system/pdl/security/Android.bp +++ b/system/pdl/security/Android.bp @@ -15,9 +15,7 @@ cc_library_headers { "BluetoothGeneratedPacketsSmp_h", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } @@ -30,9 +28,7 @@ cc_library_static { "libbluetooth_smp_pdl_header", ], host_supported: true, - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "33", } diff --git a/system/profile/avrcp/Android.bp b/system/profile/avrcp/Android.bp index 8db8f11b2a..6ea0ea1abb 100644 --- a/system/profile/avrcp/Android.bp +++ b/system/profile/avrcp/Android.bp @@ -38,9 +38,7 @@ cc_library_static { shared_libs: [ "liblog", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], } diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc index ef4fcda929..d094108d8a 100644 --- a/system/profile/avrcp/device.cc +++ b/system/profile/avrcp/device.cc @@ -766,6 +766,7 @@ void Device::GetElementAttributesResponse(uint8_t label, SongInfo info) { auto get_element_attributes_pkt = pkt; auto attributes_requested = get_element_attributes_pkt->GetAttributesRequested(); + bool all_attributes_flag = com::android::bluetooth::flags::get_all_element_attributes_empty(); auto response = GetElementAttributesResponseBuilder::MakeBuilder(ctrl_mtu_); @@ -780,10 +781,12 @@ void Device::GetElementAttributesResponse(uint8_t label, for (const auto& attribute : attributes_requested) { if (info.attributes.find(attribute) != info.attributes.end()) { response->AddAttributeEntry(*info.attributes.find(attribute)); + } else if (all_attributes_flag) { + response->AddAttributeEntry(attribute, std::string()); } } } else { // zero attributes requested which means all attributes requested - if (!com::android::bluetooth::flags::get_all_element_attributes_empty()) { + if (!all_attributes_flag) { for (const auto& attribute : info.attributes) { response->AddAttributeEntry(attribute); } diff --git a/system/rust/Android.bp b/system/rust/Android.bp index 592a686216..59ef358330 100644 --- a/system/rust/Android.bp +++ b/system/rust/Android.bp @@ -58,7 +58,7 @@ rust_defaults { ], }, }, - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], } rust_ffi_static { @@ -123,7 +123,7 @@ cc_library_static { ], host_supported: true, generated_sources: ["libbluetooth_core_rs_bridge_codegen"], - apex_available: ["com.android.btservices"], + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", // Bug: 286537287 this library gets linked with Rust objects but cross-language LTO // isn't supported yet. diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 2d690133f3..384c31f010 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -24,9 +24,7 @@ cc_library_static { shared_libs: [ "libchrome", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } @@ -150,9 +148,7 @@ cc_library_static { "libldacBT_abr", "libldacBT_enc", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } @@ -342,9 +338,7 @@ cc_library_static { "libPlatformProperties", "libcrypto", ], - apex_available: [ - "com.android.btservices", - ], + apex_available: ["com.android.bt"], host_supported: true, min_sdk_version: "Tiramisu", } @@ -1105,6 +1099,7 @@ cc_test { ":TestMockRustFfi", ":TestMockStackArbiter", ":TestMockStackBtm", + ":TestMockStackConnMgr", ":TestMockStackSdp", "gatt/gatt_utils.cc", "test/common/mock_eatt.cc", @@ -1639,6 +1634,7 @@ cc_test { ], static_libs: [ "bluetooth_flags_c_lib_for_test", + "libaconfig_storage_read_api_cc", "libbase", "libbluetooth-types", "libbluetooth_gd", @@ -1655,7 +1651,6 @@ cc_test { "libprotobuf-cpp-lite", "libstatslog_bt", "server_configurable_flags", - "libaconfig_storage_read_api_cc", ], target: { android: { @@ -1887,6 +1882,7 @@ cc_test { "test/hid/stack_hid_test.cc", ], static_libs: [ + "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-types", "libbluetooth_crypto_toolbox", @@ -1905,6 +1901,7 @@ cc_test { "libprotobuf-cpp-lite", ], shared_libs: [ + "libaconfig_storage_read_api_cc", "libcrypto", ], target: { @@ -1962,6 +1959,7 @@ cc_test { ], static_libs: [ "bluetooth_flags_c_lib_for_test", + "libaconfig_storage_read_api_cc", "libbase", "libbluetooth-types", "libbluetooth_gd", @@ -1977,7 +1975,6 @@ cc_test { "liblog", "libosi", "server_configurable_flags", - "libaconfig_storage_read_api_cc", ], aidl: { libs: ["bluetooth_constants"], diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc index 683e4801cd..0aeb9ceb91 100644 --- a/system/stack/acl/ble_acl.cc +++ b/system/stack/acl/ble_acl.cc @@ -50,9 +50,6 @@ static bool acl_ble_common_connection(const tBLE_BD_ADDR& address_with_type, uin btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT); } - // Inform any applications that a connection has completed. - connection_manager::on_connection_complete(address_with_type.bda); - // Allocate or update the security device record for this device btm_ble_connected(address_with_type.bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, address_with_type.type, is_in_security_db, @@ -108,8 +105,6 @@ void acl_ble_enhanced_connection_complete_from_shim( uint16_t conn_interval, uint16_t conn_latency, uint16_t conn_timeout, const RawAddress& local_rpa, const RawAddress& peer_rpa, tBLE_ADDR_TYPE peer_addr_type, bool can_read_discoverable_characteristics) { - connection_manager::on_connection_complete(address_with_type.bda); - tBLE_BD_ADDR resolved_address_with_type; const bool is_in_security_db = maybe_resolve_received_address(address_with_type, &resolved_address_with_type); diff --git a/system/stack/avdt/avdt_api.cc b/system/stack/avdt/avdt_api.cc index 3a979e9c3a..adad0da41d 100644 --- a/system/stack/avdt/avdt_api.cc +++ b/system/stack/avdt/avdt_api.cc @@ -39,7 +39,6 @@ #include "avdtc_api.h" #include "bta/include/bta_sec_api.h" #include "internal_include/bt_target.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "stack/include/a2dp_codec_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/btm/btm_ble_sec.cc b/system/stack/btm/btm_ble_sec.cc index 2ab87a0573..e05091f656 100644 --- a/system/stack/btm/btm_ble_sec.cc +++ b/system/stack/btm/btm_ble_sec.cc @@ -1595,7 +1595,7 @@ void btm_ble_connection_established(const RawAddress& bda) { } // Encrypt the link if device is bonded - if (com::android::bluetooth::flags::le_enc_on_reconnection() && + if (com::android::bluetooth::flags::le_enc_on_reconnect() && p_dev_rec->sec_rec.is_le_link_key_known()) { btm_ble_set_encryption(bda, BTM_BLE_SEC_ENCRYPT, p_dev_rec->role_central ? HCI_ROLE_CENTRAL : HCI_ROLE_PERIPHERAL); diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index f6ec70497b..9afa217b20 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -1029,7 +1029,7 @@ tBTM_STATUS BTM_SetEncryption(const RawAddress& bd_addr, tBT_TRANSPORT transport : p_dev_rec->sec_rec.classic_link; /* Enqueue security request if security is active */ - if (!com::android::bluetooth::flags::le_enc_on_reconnection()) { + if (!com::android::bluetooth::flags::le_enc_on_reconnect()) { if (p_dev_rec->sec_rec.p_callback || (p_dev_rec->sec_rec.le_link != tSECURITY_STATE::IDLE && p_dev_rec->sec_rec.classic_link != tSECURITY_STATE::IDLE)) { @@ -2167,7 +2167,7 @@ tBTM_SEC_DEV_REC* btm_rnr_add_name_to_security_record(const RawAddress* p_bd_add BTM_LogHistory(kBtmLogTag, (p_bd_addr) ? *p_bd_addr : RawAddress::kEmpty, "RNR complete", std::format("hci_status:{} name:{}", hci_error_code_text(hci_status), - PRIVATE_NAME(reinterpret_cast<char const*>(p_bd_name)))); + reinterpret_cast<char const*>(p_bd_name))); if (p_dev_rec == nullptr) { // We need to send the callbacks to complete the RNR cycle despite failure @@ -4632,7 +4632,9 @@ static void btm_sec_wait_and_start_authentication(tBTM_SEC_DEV_REC* p_dev_rec) { /* Overwrite the system-wide authentication delay if device-specific * interoperability delay is needed. */ - if (interop_match_addr(INTEROP_DELAY_AUTH, addr)) { + if (interop_match_addr(INTEROP_DELAY_AUTH, addr) || + interop_match_name(INTEROP_DELAY_AUTH, + reinterpret_cast<char const*>(p_dev_rec->sec_bd_name))) { delay_auth = BTM_SEC_START_AUTH_DELAY; } @@ -4972,7 +4974,7 @@ static void btm_sec_check_pending_enc_req(tBTM_SEC_DEV_REC* p_dev_rec, tBT_TRANS node = list_next(node); log::debug("btm_sec_check_pending_enc_req : sec_act=0x{:x}", p_e->sec_act); if (p_e->bd_addr == p_dev_rec->bd_addr && p_e->psm == 0 && p_e->transport == transport) { - if (!com::android::bluetooth::flags::le_enc_on_reconnection()) { + if (!com::android::bluetooth::flags::le_enc_on_reconnect()) { if (encr_enable == 0 || transport == BT_TRANSPORT_BR_EDR || p_e->sec_act == BTM_BLE_SEC_ENCRYPT || p_e->sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM || (p_e->sec_act == BTM_BLE_SEC_ENCRYPT_MITM && diff --git a/system/stack/btm/security_device_record.h b/system/stack/btm/security_device_record.h index 94e48753d2..61a6d182a6 100644 --- a/system/stack/btm/security_device_record.h +++ b/system/stack/btm/security_device_record.h @@ -25,7 +25,6 @@ #include "internal_include/bt_target.h" #include "macros.h" -#include "os/logging/log_adapter.h" #include "stack/include/bt_device_type.h" #include "stack/include/bt_name.h" #include "stack/include/bt_octets.h" @@ -330,7 +329,7 @@ public: "name:\"{}\" sec_prop:{}", bd_addr, DeviceTypeText(device_type), dev_class_text(dev_class), remote_version_info.ToString(), sm4, remote_supports_secure_connections ? 'T' : 'F', - PRIVATE_NAME(reinterpret_cast<char const*>(sec_bd_name)), sec_rec.ToString()); + reinterpret_cast<char const*>(sec_bd_name), sec_rec.ToString()); } public: diff --git a/system/stack/connection_manager/connection_manager.cc b/system/stack/connection_manager/connection_manager.cc index 11d4637b56..502bf8747b 100644 --- a/system/stack/connection_manager/connection_manager.cc +++ b/system/stack/connection_manager/connection_manager.cc @@ -31,7 +31,6 @@ #include "main/shim/acl_api.h" #include "main/shim/entry.h" #include "main/shim/le_scanning_manager.h" -#include "os/logging/log_adapter.h" #include "osi/include/alarm.h" #include "stack/btm/btm_dev.h" #include "stack/include/advertise_data_parser.h" @@ -368,7 +367,7 @@ bool background_connect_remove(uint8_t app_id, const RawAddress& address) { } if (is_anyone_connecting(it)) { - log::debug("some device is still connecting, app_id={}, address={}", static_cast<int>(app_id), + log::debug("some app is still connecting, app_id={}, address={}", static_cast<int>(app_id), address); /* Check which method should be used now.*/ if (!accept_list_enabled) { diff --git a/system/stack/eatt/eatt.h b/system/stack/eatt/eatt.h index c47509def7..b4ab901551 100644 --- a/system/stack/eatt/eatt.h +++ b/system/stack/eatt/eatt.h @@ -21,7 +21,6 @@ #include <deque> #include <memory> -#include "os/logging/log_adapter.h" #include "stack/gatt/gatt_int.h" #include "types/raw_address.h" diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc index 19ea3a3090..3e10a8b660 100644 --- a/system/stack/gatt/gatt_api.cc +++ b/system/stack/gatt/gatt_api.cc @@ -1486,14 +1486,7 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBLE_ADDR_TYPE ad /* Consider to remove gatt_act_connect at all */ ret = gatt_act_connect(p_reg, bd_addr, addr_type, transport, initiating_phys); } else { - log::verbose("Connecting without tcb address: {}", bd_addr); - - if (p_reg->direct_connect_request.count(bd_addr) == 0) { - p_reg->direct_connect_request.insert(bd_addr); - } else { - log::warn("{} already added to gatt_if {} direct conn list", bd_addr, gatt_if); - } - + log::verbose("Connecting without tcb to: {}", bd_addr); ret = connection_manager::direct_connect_add(gatt_if, bd_addr, addr_type); } diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h index db0d0da9ca..906c99eb2f 100644 --- a/system/stack/gatt/gatt_int.h +++ b/system/stack/gatt/gatt_int.h @@ -33,7 +33,6 @@ #include "gatt_api.h" #include "internal_include/bt_target.h" #include "macros.h" -#include "os/logging/log_adapter.h" #include "osi/include/fixed_queue.h" #include "stack/include/bt_hdr.h" #include "types/bluetooth/uuid.h" @@ -194,7 +193,6 @@ typedef struct { uint8_t listening{0}; /* if adv for all has been enabled */ bool eatt_support{false}; std::string name; - std::set<RawAddress> direct_connect_request; std::map<RawAddress, uint16_t> mtu_prefs; } tGATT_REG; @@ -491,7 +489,6 @@ extern bluetooth::common::TimestampedCircularBuffer<tTCB_STATE_HISTORY> tcb_stat /* from gatt_main.cc */ bool gatt_disconnect(tGATT_TCB* p_tcb); -void gatt_cancel_connect(const RawAddress& bd_addr, tBT_TRANSPORT transport); bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, tBT_TRANSPORT transport, int8_t initiating_phys); bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc index 0d8d51d846..2688cfa582 100644 --- a/system/stack/gatt/gatt_main.cc +++ b/system/stack/gatt/gatt_main.cc @@ -240,32 +240,6 @@ static bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tG /******************************************************************************* * - * Function gatt_cancel_connect - * - * Description This will remove device from allow list and cancel connection - * - * Parameter bd_addr: peer device address. - * transport: transport - * - * - ******************************************************************************/ -void gatt_cancel_connect(const RawAddress& bd_addr, tBT_TRANSPORT transport) { - /* This shall be call only when device is not connected */ - log::debug("{}, transport {}", bd_addr, transport); - - if (!connection_manager::direct_connect_remove(CONN_MGR_ID_L2CAP, bd_addr)) { - bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bd_addr)); - log::info( - "GATT connection manager has no record but removed filter " - "acceptlist gatt_if:{} peer:{}", - static_cast<uint8_t>(CONN_MGR_ID_L2CAP), bd_addr); - } - - gatt_cleanup_upon_disc(bd_addr, GATT_CONN_TERMINATE_LOCAL_HOST, transport); -} - -/******************************************************************************* - * * Function gatt_disconnect * * Description This function is called to disconnect to an ATT device. @@ -290,29 +264,42 @@ bool gatt_disconnect(tGATT_TCB* p_tcb) { return true; } - if (p_tcb->att_lcid == L2CAP_ATT_CID) { - if (ch_state == GATT_CH_OPEN) { - if (com::android::bluetooth::flags::gatt_disconnect_fix() && p_tcb->eatt) { - /* ATT is fixed channel and it is expected to drop ACL. - * Make sure all EATT channels are disconnected before doing that. - */ - EattExtension::GetInstance()->Disconnect(p_tcb->peer_bda); - } - if (!stack::l2cap::get_interface().L2CA_RemoveFixedChnl(L2CAP_ATT_CID, p_tcb->peer_bda)) { - log::warn("Unable to remove L2CAP ATT fixed channel peer:{}", p_tcb->peer_bda); - } - gatt_set_ch_state(p_tcb, GATT_CH_CLOSING); - } else { - gatt_cancel_connect(p_tcb->peer_bda, p_tcb->transport); - } - } else { + if (p_tcb->att_lcid != L2CAP_ATT_CID) { if ((ch_state == GATT_CH_OPEN) || (ch_state == GATT_CH_CFG)) { gatt_l2cif_disconnect(p_tcb->att_lcid); } else { log::verbose("gatt_disconnect channel not opened"); } + return true; + } + + /* att_lcid == L2CAP_ATT_CID */ + + if (ch_state != GATT_CH_OPEN) { + if (!connection_manager::direct_connect_remove(CONN_MGR_ID_L2CAP, p_tcb->peer_bda)) { + bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(p_tcb->peer_bda)); + log::info( + "GATT connection manager has no record but removed filter " + "acceptlist gatt_if:{} peer:{}", + static_cast<uint8_t>(CONN_MGR_ID_L2CAP), p_tcb->peer_bda); + } + + gatt_cleanup_upon_disc(p_tcb->peer_bda, GATT_CONN_TERMINATE_LOCAL_HOST, p_tcb->transport); + return true; + } + + if (com::android::bluetooth::flags::gatt_disconnect_fix() && p_tcb->eatt) { + /* ATT is fixed channel and it is expected to drop ACL. + * Make sure all EATT channels are disconnected before doing that. + */ + EattExtension::GetInstance()->Disconnect(p_tcb->peer_bda); + } + + if (!stack::l2cap::get_interface().L2CA_RemoveFixedChnl(L2CAP_ATT_CID, p_tcb->peer_bda)) { + log::warn("Unable to remove L2CAP ATT fixed channel peer:{}", p_tcb->peer_bda); } + gatt_set_ch_state(p_tcb, GATT_CH_CLOSING); return true; } @@ -1004,13 +991,6 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) { gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true); } - if (p_reg->direct_connect_request.count(p_tcb->peer_bda) > 0) { - gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true); - log::info("Removing device {} from the direct connect list of gatt_if {}", p_tcb->peer_bda, - p_reg->gatt_if); - p_reg->direct_connect_request.erase(p_tcb->peer_bda); - } - if (p_reg->app_cb.p_conn_cb) { conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, kGattConnected, @@ -1027,13 +1007,6 @@ static void gatt_send_conn_cback(tGATT_TCB* p_tcb) { gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true); } - if (p_reg->direct_connect_request.count(p_tcb->peer_bda) > 0) { - gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true); - log::info("Removing device {} from the direct connect list of gatt_if {}", p_tcb->peer_bda, - p_reg->gatt_if); - p_reg->direct_connect_request.erase(p_tcb->peer_bda); - } - if (p_reg->app_cb.p_conn_cb) { conn_id = gatt_create_conn_id(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, kGattConnected, diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc index 88ecfe2d53..57f781db3f 100644 --- a/system/stack/gatt/gatt_utils.cc +++ b/system/stack/gatt/gatt_utils.cc @@ -1581,46 +1581,25 @@ void gatt_sr_update_prep_cnt(tGATT_TCB& tcb, tGATT_IF gatt_if, bool is_inc, bool } } -static bool gatt_is_anybody_interested_in_connection(const RawAddress& bda) { - if (connection_manager::is_background_connection(bda)) { - log::debug("{} is in background connection", bda); - return true; +/** Cancel LE Create Connection request */ +bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { + if (connection_manager::direct_connect_remove(gatt_if, bda)) { + log::info("{} was doing direct connect to {}, canceled", gatt_if, bda); } - - for (size_t i = 1; i <= GATT_MAX_APPS; i++) { - tGATT_REG* p_reg = &gatt_cb.cl_rcb[i - 1]; - if (p_reg->in_use && p_reg->direct_connect_request.count(bda) > 0) { - log::debug("gatt_if {} interested in connection to {}", i, bda); - return true; - } + if (connection_manager::background_connect_remove(gatt_if, bda)) { + log::info("{} was doing background connect to {}, canceled", gatt_if, bda); } - return false; -} -/** Cancel LE Create Connection request */ -bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE); if (!p_tcb) { - /* TCB is not allocated when trying to connect under this flag. - * but device address is storred in the tGATT_REG. Make sure to remove - * the address from the list when cancel is called. - */ - - tGATT_REG* p_reg = gatt_get_regcb(gatt_if); - if (!p_reg) { - log::error("Unable to find registered app gatt_if={}", gatt_if); - } else { - log::info("Removing {} from direct list", bda); - p_reg->direct_connect_request.erase(bda); - } - if (!gatt_is_anybody_interested_in_connection(bda)) { - gatt_cancel_connect(bda, static_cast<tBT_TRANSPORT>(BT_TRANSPORT_LE)); + if (connection_manager::get_apps_connecting_to(bda).empty()) { + gatt_cleanup_upon_disc(bda, GATT_CONN_TERMINATE_LOCAL_HOST, BT_TRANSPORT_LE); } return true; } if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) { - log::error("link connected Too late to cancel"); + log::error("link connected too late to cancel {}", bda); return false; } @@ -1632,24 +1611,6 @@ bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { gatt_disconnect(p_tcb); } - if (!connection_manager::direct_connect_remove(gatt_if, bda)) { - if (!connection_manager::is_background_connection(bda)) { - if (!com::android::bluetooth::flags::gatt_fix_multiple_direct_connect() || - p_tcb->app_hold_link.empty()) { - bluetooth::shim::ACL_IgnoreLeConnectionFrom(BTM_Sec_GetAddressWithType(bda)); - } - log::info( - "Gatt connection manager has no background record but removed " - "filter acceptlist gatt_if:{} peer:{}", - gatt_if, bda); - } else { - log::info( - "Gatt connection manager maintains a background record preserving " - "filter acceptlist gatt_if:{} peer:{}", - gatt_if, bda); - } - } - return true; } @@ -1830,12 +1791,6 @@ static void gatt_disconnect_complete_notify_user(const RawAddress& bda, tGATT_DI (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, kGattDisconnected, reason, transport); } - - if (p_reg->direct_connect_request.count(bda) > 0) { - log::info("Removing device {} from the direct connect list of gatt_if {}", bda, - p_reg->gatt_if); - p_reg->direct_connect_request.erase(bda); - } } } else { for (uint8_t i = 0; i < GATT_MAX_APPS; i++) { @@ -1846,12 +1801,6 @@ static void gatt_disconnect_complete_notify_user(const RawAddress& bda, tGATT_DI (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id, kGattDisconnected, reason, transport); } - - if (p_reg->direct_connect_request.count(bda) > 0) { - log::info("Removing device {} from the direct connect list of gatt_if {}", bda, - p_reg->gatt_if); - p_reg->direct_connect_request.erase(bda); - } } } } @@ -1906,6 +1855,9 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason, gatt_free_pending_ind(p_tcb); fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL); p_tcb->sr_cmd.multi_rsp_q = NULL; + if (p_tcb->sr_cmd.p_rsp_msg) { + osi_free_and_reset((void**)&p_tcb->sr_cmd.p_rsp_msg); + } gatt_disconnect_complete_notify_user(bda, reason, transport); diff --git a/system/stack/hid/hidh_conn.cc b/system/stack/hid/hidh_conn.cc index 83bb039173..d658c1ab29 100644 --- a/system/stack/hid/hidh_conn.cc +++ b/system/stack/hid/hidh_conn.cc @@ -24,6 +24,7 @@ #include <base/functional/callback.h> #include <bluetooth/log.h> +#include <com_android_bluetooth_flags.h> #include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h> #include <string.h> @@ -70,6 +71,8 @@ static void hidh_l2cif_connect_cfm(uint16_t l2cap_cid, tL2CAP_CONN result); static void hidh_l2cif_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg); static void hidh_l2cif_config_cfm(uint16_t l2cap_cid, uint16_t result, tL2CAP_CFG_INFO* p_cfg); static void hidh_l2cif_disconnect_ind(uint16_t l2cap_cid, bool ack_needed); +static void hidh_l2cif_disconnect_cfm(uint16_t l2cap_cid, uint16_t result); +static void hidh_l2cif_disconnect_cfm_actual(uint16_t l2cap_cid, uint16_t result); static void hidh_l2cif_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg); static void hidh_l2cif_disconnect(uint16_t l2cap_cid); static void hidh_l2cif_cong_ind(uint16_t l2cap_cid, bool congested); @@ -81,6 +84,7 @@ static const tL2CAP_APPL_INFO hst_reg_info = { .pL2CA_ConfigInd_Cb = hidh_l2cif_config_ind, .pL2CA_ConfigCfm_Cb = hidh_l2cif_config_cfm, .pL2CA_DisconnectInd_Cb = hidh_l2cif_disconnect_ind, + .pL2CA_DisconnectCfm_Cb = hidh_l2cif_disconnect_cfm, .pL2CA_DataInd_Cb = hidh_l2cif_data_ind, .pL2CA_CongestionStatus_Cb = hidh_l2cif_cong_ind, .pL2CA_TxComplete_Cb = nullptr, @@ -160,7 +164,7 @@ tHID_STATUS hidh_conn_disconnect(uint8_t dhandle) { BT_TRANSPORT_BR_EDR)) { log::warn("Unable to set L2CAP idle timeout peer:{}", hh_cb.devices[dhandle].addr); } - /* Disconnect both interrupt and control channels */ + /* Disconnect channels one by one */ if (p_hcon->intr_cid) { hidh_l2cif_disconnect(p_hcon->intr_cid); } else if (p_hcon->ctrl_cid) { @@ -553,11 +557,38 @@ static void hidh_l2cif_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) { } } +// TODO: after disconnect_hid_channels_serially aflags is the default, +// remove this function and call L2CA_DisconnectReq directly. static void hidh_l2cif_disconnect(uint16_t l2cap_cid) { if (!stack::l2cap::get_interface().L2CA_DisconnectReq(l2cap_cid)) { log::warn("Unable to send L2CAP disconnect request cid:{}", l2cap_cid); } + if (!com::android::bluetooth::flags::disconnect_hid_channels_serially()) { + hidh_l2cif_disconnect_cfm_actual(l2cap_cid, 0); + } +} + +/******************************************************************************* + * + * Function hidh_l2cif_disconnect_cfm + * + * Description This function handles a disconnect confirm from L2CAP. This + * means our disconnection request has been acknowledged, so we + * can disconnect the other channel, if required. + * + * Returns void + * + ******************************************************************************/ +static void hidh_l2cif_disconnect_cfm(uint16_t l2cap_cid, uint16_t result) { + if (com::android::bluetooth::flags::disconnect_hid_channels_serially()) { + hidh_l2cif_disconnect_cfm_actual(l2cap_cid, result); + } +} + +// TODO: after disconnect_hid_channels_serially aflags is the default, +// copy the body to hidh_l2cif_disconnect_cfm and remove this. +static void hidh_l2cif_disconnect_cfm_actual(uint16_t l2cap_cid, uint16_t /* result */) { /* Find CCB based on CID */ const uint8_t dhandle = find_conn_by_cid(l2cap_cid); if (dhandle == kHID_HOST_MAX_DEVICES) { diff --git a/system/stack/include/port_api.h b/system/stack/include/port_api.h index 3a9fd7e4b3..d515813b81 100644 --- a/system/stack/include/port_api.h +++ b/system/stack/include/port_api.h @@ -360,6 +360,19 @@ typedef void(tPORT_MGMT_CALLBACK)(const tPORT_RESULT code, uint16_t port_handle) /******************************************************************************* * + * Function PORT_SetAppUid + * + * Description This function configures connection according to the + * specifications in the tPORT_STATE structure. + * + * Parameters: handle - Handle returned in the RFCOMM_CreateConnection + * app_uid - Uid of app that requested the socket + * + ******************************************************************************/ +[[nodiscard]] int PORT_SetAppUid(uint16_t handle, uint32_t app_uid); + +/******************************************************************************* + * * Function PORT_SetState * * Description This function configures connection according to the diff --git a/system/stack/l2cap/l2c_fcr.cc b/system/stack/l2cap/l2c_fcr.cc index 5e7fc3712d..cc0bc0569a 100644 --- a/system/stack/l2cap/l2c_fcr.cc +++ b/system/stack/l2cap/l2c_fcr.cc @@ -24,6 +24,7 @@ ******************************************************************************/ #include <bluetooth/log.h> +#include <com_android_bluetooth_flags.h> #include <stdlib.h> #include <string.h> @@ -683,10 +684,19 @@ void l2c_lcc_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) { uint16_t sdu_length; BT_HDR* p_data = NULL; + uint16_t local_mps = p_ccb->local_conn_cfg.mps; + if (com::android::bluetooth::flags::fix_buf_len_check_for_first_k_frame()) { + if (p_ccb->is_first_seg) { + // for the first k-frame, donot consider sdu_length + // as part of the information payload + local_mps = p_ccb->local_conn_cfg.mps + sizeof(sdu_length); + } + } + /* Buffer length should not exceed local mps */ - if (p_buf->len > p_ccb->local_conn_cfg.mps) { + if (p_buf->len > local_mps) { log::error("buffer length={} exceeds local mps={}. Drop and disconnect.", p_buf->len, - p_ccb->local_conn_cfg.mps); + local_mps); /* Discard the buffer and disconnect*/ osi_free(p_buf); diff --git a/system/stack/pan/pan_api.cc b/system/stack/pan/pan_api.cc index 432a071ec7..8650b5d464 100644 --- a/system/stack/pan/pan_api.cc +++ b/system/stack/pan/pan_api.cc @@ -36,7 +36,6 @@ #include "bta/sys/bta_sys.h" #include "internal_include/bt_target.h" #include "main/shim/dumpsys.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/bnep_api.h" #include "stack/include/bt_hdr.h" diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc index f5f0274990..fea9367fbc 100644 --- a/system/stack/rfcomm/port_api.cc +++ b/system/stack/rfcomm/port_api.cc @@ -32,7 +32,6 @@ #include <cstdint> #include "internal_include/bt_trace.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "osi/include/mutex.h" #include "stack/include/bt_hdr.h" @@ -143,7 +142,7 @@ int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn, bool is_serv log::error( "already at opened state {}, RFC_state={}, MCB_state={}, " "bd_addr={}, scn={}, is_server={}, mtu={}, uuid=0x{:x}, dlci={}, p_mcb={}, port={}", - static_cast<int>(p_port->state), static_cast<int>(p_port->rfc.state), + static_cast<int>(p_port->state), static_cast<int>(p_port->rfc.sm_cb.state), p_port->rfc.p_mcb ? p_port->rfc.p_mcb->state : 0, bd_addr, scn, is_server, mtu, uuid, dlci, std::format_ptr(p_mcb), p_port->handle); *p_handle = p_port->handle; @@ -456,14 +455,14 @@ int PORT_CheckConnection(uint16_t handle, RawAddress* bd_addr, uint16_t* p_lcid) } log::verbose("handle={}, in_use={}, port_state={}, p_mcb={}, peer_ready={}, rfc_state={}", handle, p_port->in_use, p_port->state, std::format_ptr(p_port->rfc.p_mcb), - p_port->rfc.p_mcb ? p_port->rfc.p_mcb->peer_ready : -1, p_port->rfc.state); + p_port->rfc.p_mcb ? p_port->rfc.p_mcb->peer_ready : -1, p_port->rfc.sm_cb.state); if (!p_port->in_use || (p_port->state == PORT_CONNECTION_STATE_CLOSED)) { return PORT_NOT_OPENED; } if (!p_port->rfc.p_mcb || !p_port->rfc.p_mcb->peer_ready || - (p_port->rfc.state != RFC_STATE_OPENED)) { + (p_port->rfc.sm_cb.state != RFC_STATE_OPENED)) { return PORT_LINE_ERR; } @@ -510,8 +509,8 @@ bool PORT_IsOpening(RawAddress* bd_addr) { if (multiplexer_cb.state == RFC_MX_STATE_CONNECTED) { const tPORT* p_port = get_port_from_mcb(&multiplexer_cb); log::info("RFC_MX_STATE_CONNECTED, found_port={}, tRFC_PORT_STATE={}", - (p_port != nullptr) ? "T" : "F", (p_port != nullptr) ? p_port->rfc.state : 0); - if ((p_port == nullptr) || (p_port->rfc.state < RFC_STATE_OPENED)) { + (p_port != nullptr) ? "T" : "F", (p_port != nullptr) ? p_port->rfc.sm_cb.state : 0); + if ((p_port == nullptr) || (p_port->rfc.sm_cb.state < RFC_STATE_OPENED)) { /* Port is not established yet. */ *bd_addr = multiplexer_cb.bd_addr; log::info("In RFC_MX_STATE_CONNECTED but port is not established yet, returning true"); @@ -555,8 +554,8 @@ bool PORT_IsCollisionDetected(RawAddress bd_addr) { if (multiplexer_cb.state == RFC_MX_STATE_CONNECTED) { const tPORT* p_port = get_port_from_mcb(&multiplexer_cb); log::info("RFC_MX_STATE_CONNECTED, found_port={}, tRFC_PORT_STATE={}", - (p_port != nullptr) ? "T" : "F", (p_port != nullptr) ? p_port->rfc.state : 0); - if ((p_port == nullptr) || (p_port->rfc.state < RFC_STATE_OPENED)) { + (p_port != nullptr) ? "T" : "F", (p_port != nullptr) ? p_port->rfc.sm_cb.state : 0); + if ((p_port == nullptr) || (p_port->rfc.sm_cb.state < RFC_STATE_OPENED)) { // Port is not established yet log::info( "In RFC_MX_STATE_CONNECTED but port is not established yet, " @@ -571,6 +570,30 @@ bool PORT_IsCollisionDetected(RawAddress bd_addr) { /******************************************************************************* * + * Function PORT_SetAppUid + * + * Description This function configures connection according to the + * specifications in the tPORT_STATE structure. + * + * Parameters: handle - Handle returned in the RFCOMM_CreateConnection + * app_uid - Uid of app that requested the socket + * + ******************************************************************************/ +int PORT_SetAppUid(uint16_t handle, uint32_t app_uid) { + tPORT* p_port = get_port_from_handle(handle); + + if (p_port == nullptr) { + log::error("Unable to get RFCOMM port control block bad handle:{}", handle); + return PORT_BAD_HANDLE; + } + + p_port->app_uid = app_uid; + + return PORT_SUCCESS; +} + +/******************************************************************************* + * * Function PORT_SetSettings * * Description This function configures connection according to the @@ -829,7 +852,7 @@ int PORT_ReadData(uint16_t handle, char* p_data, uint16_t max_len, uint16_t* p_l static int port_write(tPORT* p_port, BT_HDR* p_buf) { /* We should not allow to write data in to server port when connection is not * opened */ - if (p_port->is_server && (p_port->rfc.state != RFC_STATE_OPENED)) { + if (p_port->is_server && (p_port->rfc.sm_cb.state != RFC_STATE_OPENED)) { osi_free(p_buf); return PORT_CLOSED; } @@ -838,7 +861,7 @@ static int port_write(tPORT* p_port, BT_HDR* p_buf) { /* Peer is not ready or Port is not yet opened or initial port control */ /* command has not been sent */ if (p_port->tx.peer_fc || !p_port->rfc.p_mcb || !p_port->rfc.p_mcb->peer_ready || - (p_port->rfc.state != RFC_STATE_OPENED) || + (p_port->rfc.sm_cb.state != RFC_STATE_OPENED) || ((p_port->port_ctrl & (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED)) != (PORT_CTRL_REQ_SENT | PORT_CTRL_IND_RECEIVED))) { if ((p_port->tx.queue_size > PORT_TX_CRITICAL_WM) || @@ -858,7 +881,7 @@ static int port_write(tPORT* p_port, BT_HDR* p_buf) { "Data is enqueued. flow disabled {} peer_ready {} state {} ctrl_state " "{:x}", p_port->tx.peer_fc, p_port->rfc.p_mcb && p_port->rfc.p_mcb->peer_ready, - p_port->rfc.state, p_port->port_ctrl); + p_port->rfc.sm_cb.state, p_port->port_ctrl); fixed_queue_enqueue(p_port->tx.queue, p_buf); p_port->tx.queue_size += p_buf->len; diff --git a/system/stack/rfcomm/port_int.h b/system/stack/rfcomm/port_int.h index 94d9f4cc8b..6854ba9524 100644 --- a/system/stack/rfcomm/port_int.h +++ b/system/stack/rfcomm/port_int.h @@ -34,6 +34,7 @@ #include "stack/include/l2cap_types.h" #include "stack/include/port_api.h" #include "stack/include/rfcdefs.h" +#include "stack/rfcomm/rfc_event.h" #include "stack/rfcomm/rfc_state.h" #include "types/raw_address.h" @@ -45,7 +46,7 @@ #define PORT_FC_CREDIT 2 /* use RFCOMM credit based flow control */ /* - * Define Port Data Transfere control block + * Define Port Data Transfer control block */ typedef struct { fixed_queue_t* queue; /* Queue of buffers waiting to be sent */ @@ -104,10 +105,22 @@ typedef struct { } tRFC_MCB; /* + * RFCOMM Port State Machine Control Block + */ +struct RfcommPortSm { + tRFC_PORT_STATE state; + tRFC_PORT_STATE state_prior; + tRFC_PORT_EVENT last_event; + tPORT_RESULT close_reason; + uint64_t open_timestamp; + uint64_t close_timestamp; +}; + +/* * RFCOMM Port Connection Control Block */ typedef struct { - tRFC_PORT_STATE state; /* Current state of the connection */ + RfcommPortSm sm_cb; // State machine control block #define RFC_RSP_PN 0x01 #define RFC_RSP_RPN_REPLY 0x02 @@ -155,8 +168,9 @@ typedef struct { tPORT_CONNECTION_STATE state; /* State of the application */ - uint8_t scn; /* Service channel number */ - uint16_t uuid; /* Service UUID */ + uint8_t scn; /* Service channel number */ + uint16_t uuid; /* Service UUID */ + uint32_t app_uid; /* UID of the app for which this socket was created */ RawAddress bd_addr; /* BD ADDR of the device for the multiplexer channel */ bool is_server; /* true if the server application */ diff --git a/system/stack/rfcomm/port_rfc.cc b/system/stack/rfcomm/port_rfc.cc index 01c8270869..e7813a240f 100644 --- a/system/stack/rfcomm/port_rfc.cc +++ b/system/stack/rfcomm/port_rfc.cc @@ -36,7 +36,6 @@ #include "internal_include/bt_target.h" #include "internal_include/bt_trace.h" #include "main/shim/entry.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "osi/include/mutex.h" #include "stack/include/bt_hdr.h" @@ -181,7 +180,7 @@ void port_start_close(tPORT* p_port) { } /* Check if RFCOMM side has been closed while the message was queued */ - if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) { + if ((p_mcb == NULL) || (p_port->rfc.sm_cb.state == RFC_STATE_CLOSED)) { /* Call management callback function before calling port_release_port() to * clear tPort */ if (p_port->p_mgmt_callback) { @@ -900,7 +899,7 @@ void PORT_FlowInd(tRFC_MCB* p_mcb, uint8_t dlci, bool enable_data) { if (dlci == 0) { p_port = &rfc_cb.port.port[i]; if (!p_port->in_use || (p_port->rfc.p_mcb != p_mcb) || - (p_port->rfc.state != RFC_STATE_OPENED)) { + (p_port->rfc.sm_cb.state != RFC_STATE_OPENED)) { continue; } } @@ -992,7 +991,7 @@ void port_rfc_closed(tPORT* p_port, uint8_t res) { log::warn("port_rfc_closed in OPENING state ignored"); rfc_port_timer_stop(p_port); - p_port->rfc.state = RFC_STATE_CLOSED; + p_port->rfc.sm_cb.state = RFC_STATE_CLOSED; if (p_mcb) { p_mcb->port_handles[p_port->dlci] = 0; @@ -1050,7 +1049,7 @@ void port_rfc_closed(tPORT* p_port, uint8_t res) { p_port->p_mgmt_callback(static_cast<tPORT_RESULT>(res2), p_port->handle); } - p_port->rfc.state = RFC_STATE_CLOSED; + p_port->rfc.sm_cb.state = RFC_STATE_CLOSED; log::info( "RFCOMM connection closed, index={}, state={}, reason={}[{}], " diff --git a/system/stack/rfcomm/port_utils.cc b/system/stack/rfcomm/port_utils.cc index 25e1da9f4c..dc59e58987 100644 --- a/system/stack/rfcomm/port_utils.cc +++ b/system/stack/rfcomm/port_utils.cc @@ -199,8 +199,8 @@ void port_select_mtu(tPORT* p_port) { * ******************************************************************************/ void port_release_port(tPORT* p_port) { - log::verbose("p_port: {} state: {} keep_handle: {}", std::format_ptr(p_port), p_port->rfc.state, - p_port->keep_port_handle); + log::verbose("p_port: {} state: {} keep_handle: {}", std::format_ptr(p_port), + p_port->rfc.sm_cb.state, p_port->keep_port_handle); mutex_global_lock(); BT_HDR* p_buf; @@ -219,7 +219,7 @@ void port_release_port(tPORT* p_port) { p_port->state = PORT_CONNECTION_STATE_CLOSED; - if (p_port->rfc.state == RFC_STATE_CLOSED) { + if (p_port->rfc.sm_cb.state == RFC_STATE_CLOSED) { if (p_port->rfc.p_mcb) { p_port->rfc.p_mcb->port_handles[p_port->dlci] = 0; @@ -228,6 +228,7 @@ void port_release_port(tPORT* p_port) { } rfc_port_timer_stop(p_port); + p_port->rfc.sm_cb = {}; mutex_global_lock(); fixed_queue_free(p_port->tx.queue, nullptr); diff --git a/system/stack/rfcomm/rfc_port_fsm.cc b/system/stack/rfcomm/rfc_port_fsm.cc index 0f3ec064ff..040315d276 100644 --- a/system/stack/rfcomm/rfc_port_fsm.cc +++ b/system/stack/rfcomm/rfc_port_fsm.cc @@ -77,11 +77,11 @@ void rfc_port_sm_execute(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data) { log::assert_that(p_port != nullptr, "NULL port event {}", event); // logs for state RFC_STATE_OPENED handled in rfc_port_sm_opened() - if (p_port->rfc.state != RFC_STATE_OPENED) { + if (p_port->rfc.sm_cb.state != RFC_STATE_OPENED) { log::info("bd_addr:{}, handle:{}, state:{}, event:{}", p_port->bd_addr, p_port->handle, - rfcomm_port_state_text(p_port->rfc.state), rfcomm_port_event_text(event)); + rfcomm_port_state_text(p_port->rfc.sm_cb.state), rfcomm_port_event_text(event)); } - switch (p_port->rfc.state) { + switch (p_port->rfc.sm_cb.state) { case RFC_STATE_CLOSED: rfc_port_sm_state_closed(p_port, event, p_data); break; @@ -122,7 +122,7 @@ void rfc_port_sm_execute(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data) { void rfc_port_sm_state_closed(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data) { switch (event) { case RFC_PORT_EVENT_OPEN: - p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK; + p_port->rfc.sm_cb.state = RFC_STATE_ORIG_WAIT_SEC_CHECK; btm_sec_mx_access_request(p_port->rfc.p_mcb->bd_addr, true, p_port->sec_mask, &rfc_sec_check_complete, p_port); return; @@ -143,7 +143,7 @@ void rfc_port_sm_state_closed(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data rfc_timer_stop(p_port->rfc.p_mcb); /* Open will be continued after security checks are passed */ - p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK; + p_port->rfc.sm_cb.state = RFC_STATE_TERM_WAIT_SEC_CHECK; btm_sec_mx_access_request(p_port->rfc.p_mcb->bd_addr, false, p_port->sec_mask, &rfc_sec_check_complete, p_port); return; @@ -167,11 +167,11 @@ void rfc_port_sm_state_closed(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data case RFC_PORT_EVENT_TIMEOUT: PORT_TimeOutCloseMux(p_port->rfc.p_mcb); - log::error("Port error state {} event {}", p_port->rfc.state, event); + log::error("Port error state {} event {}", p_port->rfc.sm_cb.state, event); return; default: log::error("Received unexpected event:{} in state:{}", rfcomm_port_event_text(event), - rfcomm_port_state_text(p_port->rfc.state)); + rfcomm_port_state_text(p_port->rfc.sm_cb.state)); } log::warn("Event ignored {}", rfcomm_port_event_text(event)); @@ -199,7 +199,7 @@ void rfc_port_sm_sabme_wait_ua(tPORT* p_port, tRFC_PORT_EVENT event, void* p_dat rfc_port_timer_start(p_port, RFC_DISC_TIMEOUT); rfc_send_disc(p_port->rfc.p_mcb, p_port->dlci); p_port->rfc.expected_rsp = 0; - p_port->rfc.state = RFC_STATE_DISC_WAIT_UA; + p_port->rfc.sm_cb.state = RFC_STATE_DISC_WAIT_UA; return; case RFC_PORT_EVENT_CLEAR: @@ -213,7 +213,7 @@ void rfc_port_sm_sabme_wait_ua(tPORT* p_port, tRFC_PORT_EVENT event, void* p_dat case RFC_PORT_EVENT_UA: rfc_port_timer_stop(p_port); - p_port->rfc.state = RFC_STATE_OPENED; + p_port->rfc.sm_cb.state = RFC_STATE_OPENED; if (uuid_logging_acceptlist.find(p_port->uuid) != uuid_logging_acceptlist.end()) { // Find Channel Control Block by Channel ID @@ -267,13 +267,13 @@ void rfc_port_sm_sabme_wait_ua(tPORT* p_port, tRFC_PORT_EVENT event, void* p_dat return; case RFC_PORT_EVENT_TIMEOUT: - p_port->rfc.state = RFC_STATE_CLOSED; + p_port->rfc.sm_cb.state = RFC_STATE_CLOSED; PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR); return; default: log::error("Received unexpected event:{} in state:{}", rfcomm_port_event_text(event), - rfcomm_port_state_text(static_cast<tRFC_PORT_STATE>(p_port->rfc.state))); + rfcomm_port_state_text(static_cast<tRFC_PORT_STATE>(p_port->rfc.sm_cb.state))); } log::warn("Event ignored {}", rfcomm_port_event_text(event)); } @@ -296,7 +296,7 @@ void rfc_port_sm_term_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* if (*((tBTM_STATUS*)p_data) != tBTM_STATUS::BTM_SUCCESS) { log::error("Security check failed result:{} state:{} port_handle:{}", btm_status_text(*((tBTM_STATUS*)p_data)), - rfcomm_port_state_text(p_port->rfc.state), p_port->handle); + rfcomm_port_state_text(p_port->rfc.sm_cb.state), p_port->handle); /* Authentication/authorization failed. If link is still */ /* up send DM and check if we need to start inactive timer */ if (p_port->rfc.p_mcb) { @@ -306,7 +306,7 @@ void rfc_port_sm_term_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* } } else { log::debug("Security check succeeded state:{} port_handle:{}", - rfcomm_port_state_text(static_cast<tRFC_PORT_STATE>(p_port->rfc.state)), + rfcomm_port_state_text(static_cast<tRFC_PORT_STATE>(p_port->rfc.sm_cb.state)), p_port->handle); PORT_DlcEstablishInd(p_port->rfc.p_mcb, p_port->dlci, p_port->rfc.p_mcb->peer_l2cap_mtu); } @@ -334,7 +334,7 @@ void rfc_port_sm_term_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* case RFC_PORT_EVENT_DISC: btm_sec_abort_access_req(p_port->rfc.p_mcb->bd_addr); - p_port->rfc.state = RFC_STATE_CLOSED; + p_port->rfc.sm_cb.state = RFC_STATE_CLOSED; rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci); PORT_DlcReleaseInd(p_port->rfc.p_mcb, p_port->dlci); @@ -351,7 +351,7 @@ void rfc_port_sm_term_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* } } else { rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci); - p_port->rfc.state = RFC_STATE_OPENED; + p_port->rfc.sm_cb.state = RFC_STATE_OPENED; if (uuid_logging_acceptlist.find(p_port->uuid) != uuid_logging_acceptlist.end()) { // Find Channel Control Block by Channel ID @@ -378,7 +378,7 @@ void rfc_port_sm_term_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* return; default: log::error("Received unexpected event:{} in state:{}", rfcomm_port_event_text(event), - rfcomm_port_state_text(p_port->rfc.state)); + rfcomm_port_state_text(p_port->rfc.sm_cb.state)); } log::warn("Event ignored {}", event); } @@ -400,16 +400,16 @@ void rfc_port_sm_orig_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* if (*((tBTM_STATUS*)p_data) != tBTM_STATUS::BTM_SUCCESS) { log::error("Security check failed result:{} state:{} handle:{}", btm_status_text(*((tBTM_STATUS*)p_data)), - rfcomm_port_state_text(p_port->rfc.state), p_port->handle); + rfcomm_port_state_text(p_port->rfc.sm_cb.state), p_port->handle); p_port->rfc.p_mcb->is_disc_initiator = true; PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci, 0, RFCOMM_SECURITY_ERR); rfc_port_closed(p_port); } else { log::debug("Security check succeeded state:{} handle:{}", - rfcomm_port_state_text(p_port->rfc.state), p_port->handle); + rfcomm_port_state_text(p_port->rfc.sm_cb.state), p_port->handle); rfc_send_sabme(p_port->rfc.p_mcb, p_port->dlci); rfc_port_timer_start(p_port, RFC_PORT_T1_TIMEOUT); - p_port->rfc.state = RFC_STATE_SABME_WAIT_UA; + p_port->rfc.sm_cb.state = RFC_STATE_SABME_WAIT_UA; } return; @@ -434,7 +434,7 @@ void rfc_port_sm_orig_wait_sec_check(tPORT* p_port, tRFC_PORT_EVENT event, void* return; default: log::error("Received unexpected event:{} in state:{}", rfcomm_port_event_text(event), - rfcomm_port_state_text(p_port->rfc.state)); + rfcomm_port_state_text(p_port->rfc.sm_cb.state)); } log::warn("Event ignored {}", rfcomm_port_event_text(event)); } @@ -462,7 +462,7 @@ void rfc_port_sm_opened(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data) { rfc_port_timer_start(p_port, RFC_DISC_TIMEOUT); rfc_send_disc(p_port->rfc.p_mcb, p_port->dlci); p_port->rfc.expected_rsp = 0; - p_port->rfc.state = RFC_STATE_DISC_WAIT_UA; + p_port->rfc.sm_cb.state = RFC_STATE_DISC_WAIT_UA; return; case RFC_PORT_EVENT_CLEAR: @@ -510,7 +510,7 @@ void rfc_port_sm_opened(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data) { case RFC_PORT_EVENT_DISC: log::info("RFC_PORT_EVENT_DISC bd_addr:{} handle:{} dlci:{} scn:{}", p_port->bd_addr, p_port->handle, p_port->dlci, p_port->scn); - p_port->rfc.state = RFC_STATE_CLOSED; + p_port->rfc.sm_cb.state = RFC_STATE_CLOSED; rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci); if (!fixed_queue_is_empty(p_port->rx.queue)) { /* give a chance to upper stack to close port properly */ @@ -607,7 +607,7 @@ void rfc_port_sm_disc_wait_ua(tPORT* p_port, tRFC_PORT_EVENT event, void* p_data return; default: log::error("Received unexpected event:{} in state:{}", rfcomm_port_event_text(event), - rfcomm_port_state_text(p_port->rfc.state)); + rfcomm_port_state_text(p_port->rfc.sm_cb.state)); } log::warn("Event ignored {}", rfcomm_port_event_text(event)); diff --git a/system/stack/rfcomm/rfc_port_if.cc b/system/stack/rfcomm/rfc_port_if.cc index 0973f0370a..af6906fbb5 100644 --- a/system/stack/rfcomm/rfc_port_if.cc +++ b/system/stack/rfcomm/rfc_port_if.cc @@ -257,7 +257,8 @@ void RFCOMM_ControlReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_CTRL* p_pars) { return; } - if ((p_port->state != PORT_CONNECTION_STATE_OPENED) || (p_port->rfc.state != RFC_STATE_OPENED)) { + if ((p_port->state != PORT_CONNECTION_STATE_OPENED) || + (p_port->rfc.sm_cb.state != RFC_STATE_OPENED)) { return; } @@ -285,7 +286,8 @@ void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, bool enable) { return; } - if ((p_port->state != PORT_CONNECTION_STATE_OPENED) || (p_port->rfc.state != RFC_STATE_OPENED)) { + if ((p_port->state != PORT_CONNECTION_STATE_OPENED) || + (p_port->rfc.sm_cb.state != RFC_STATE_OPENED)) { return; } @@ -312,7 +314,8 @@ void RFCOMM_LineStatusReq(tRFC_MCB* p_mcb, uint8_t dlci, uint8_t status) { return; } - if ((p_port->state != PORT_CONNECTION_STATE_OPENED) || (p_port->rfc.state != RFC_STATE_OPENED)) { + if ((p_port->state != PORT_CONNECTION_STATE_OPENED) || + (p_port->rfc.sm_cb.state != RFC_STATE_OPENED)) { return; } diff --git a/system/stack/rfcomm/rfc_ts_frames.cc b/system/stack/rfcomm/rfc_ts_frames.cc index 495d0aea08..fe92bb7ef0 100644 --- a/system/stack/rfcomm/rfc_ts_frames.cc +++ b/system/stack/rfcomm/rfc_ts_frames.cc @@ -28,7 +28,6 @@ #include <cstdint> -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/rfcdefs.h" diff --git a/system/stack/rfcomm/rfc_utils.cc b/system/stack/rfcomm/rfc_utils.cc index 29b89258f7..87beaaf566 100644 --- a/system/stack/rfcomm/rfc_utils.cc +++ b/system/stack/rfcomm/rfc_utils.cc @@ -29,7 +29,6 @@ #include <cstdint> #include "internal_include/bt_target.h" -#include "os/logging/log_adapter.h" #include "osi/include/allocator.h" #include "stack/include/bt_hdr.h" #include "stack/include/port_ext.h" @@ -320,8 +319,8 @@ void rfc_sec_check_complete(RawAddress /* bd_addr */, tBT_TRANSPORT /* transport tPORT* p_port = (tPORT*)p_ref_data; /* Verify that PORT is still waiting for Security to complete */ - if (!p_port->in_use || ((p_port->rfc.state != RFC_STATE_ORIG_WAIT_SEC_CHECK) && - (p_port->rfc.state != RFC_STATE_TERM_WAIT_SEC_CHECK))) { + if (!p_port->in_use || ((p_port->rfc.sm_cb.state != RFC_STATE_ORIG_WAIT_SEC_CHECK) && + (p_port->rfc.sm_cb.state != RFC_STATE_TERM_WAIT_SEC_CHECK))) { return; } @@ -342,7 +341,7 @@ void rfc_sec_check_complete(RawAddress /* bd_addr */, tBT_TRANSPORT /* transport void rfc_port_closed(tPORT* p_port) { tRFC_MCB* p_mcb = p_port->rfc.p_mcb; rfc_port_timer_stop(p_port); - p_port->rfc.state = RFC_STATE_CLOSED; + p_port->rfc.sm_cb.state = RFC_STATE_CLOSED; /* If multiplexer channel was up mark it as down */ if (p_mcb) { diff --git a/system/stack/test/a2dp/AndroidTest.xml b/system/stack/test/a2dp/AndroidTest.xml index 71fc46cdb9..ace94ad9b8 100644 --- a/system/stack/test/a2dp/AndroidTest.xml +++ b/system/stack/test/a2dp/AndroidTest.xml @@ -34,7 +34,7 @@ <!-- Only run tests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/system/stack/test/a2dp/AndroidTestForce32.xml b/system/stack/test/a2dp/AndroidTestForce32.xml index c2fa5e44dc..afb13d3266 100644 --- a/system/stack/test/a2dp/AndroidTestForce32.xml +++ b/system/stack/test/a2dp/AndroidTestForce32.xml @@ -33,7 +33,7 @@ <!-- Only run tests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.android.btservices" /> - <option name="mainline-module-package-name" value="com.google.android.btservices" /> + <option name="mainline-module-package-name" value="com.android.bt" /> + <option name="mainline-module-package-name" value="com.google.android.bt" /> </object> </configuration> diff --git a/system/stack/test/gatt/gatt_sr_test.cc b/system/stack/test/gatt/gatt_sr_test.cc index 285aa23ea8..9c5eb868d0 100644 --- a/system/stack/test/gatt/gatt_sr_test.cc +++ b/system/stack/test/gatt/gatt_sr_test.cc @@ -53,16 +53,6 @@ struct TestMutables { TestMutables test_state_; } // namespace -namespace connection_manager { -bool background_connect_remove(uint8_t /*app_id*/, const RawAddress& /*address*/) { return false; } -bool direct_connect_remove(uint8_t /*app_id*/, const RawAddress& /*address*/, - bool /*connection_timeout*/) { - return false; -} -bool is_background_connection(const RawAddress& /*address*/) { return false; } - -} // namespace connection_manager - BT_HDR* attp_build_sr_msg(tGATT_TCB& /*tcb*/, uint8_t op_code, tGATT_SR_MSG* /*p_msg*/, uint16_t /*payload_size*/) { test_state_.attp_build_sr_msg.op_code_ = op_code; @@ -81,7 +71,6 @@ tGATT_STATUS attp_send_sr_msg(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, BT_HDR* /*p_ void gatt_act_discovery(tGATT_CLCB* /*p_clcb*/) {} bool gatt_disconnect(tGATT_TCB* /*p_tcb*/) { return false; } -void gatt_cancel_connect(const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {} tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* /*p_tcb*/) { return GATT_CH_CLOSE; } tGATT_STATUS gatts_db_read_attr_value_by_type(tGATT_TCB& /*tcb*/, uint16_t /*cid*/, tGATT_SVC_DB* /*p_db*/, uint8_t /*op_code*/, diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc index a7b9082824..f4df22397b 100644 --- a/system/stack/test/gatt/mock_gatt_utils_ref.cc +++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc @@ -46,7 +46,6 @@ void gatt_update_app_use_link_flag(tGATT_IF /*gatt_if*/, tGATT_TCB* /*p_tcb*/, b bool /*check_acl_link*/) {} void gatts_proc_srv_chg_ind_ack(tGATT_TCB) {} bool gatt_disconnect(tGATT_TCB* /*p_tcb*/) { return false; } -void gatt_cancel_connect(const RawAddress& /*bd_addr*/, tBT_TRANSPORT /*transport*/) {} tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* /*p_tcb*/) { return GATT_CH_CLOSE; } void gatt_set_ch_state(tGATT_TCB* /*p_tcb*/, tGATT_CH_STATE /*ch_state*/) {} diff --git a/system/stack/test/gatt/stack_gatt_test.cc b/system/stack/test/gatt/stack_gatt_test.cc index 71928440a4..9f0cacf48a 100644 --- a/system/stack/test/gatt/stack_gatt_test.cc +++ b/system/stack/test/gatt/stack_gatt_test.cc @@ -124,7 +124,6 @@ TEST_F(StackGattTest, lifecycle_tGATT_REG) { memset(reg0.get(), 0, sizeof(tGATT_REG)); // Restore the complex structure after memset memset(®1.name, 0, sizeof(std::string)); - memset(®1.direct_connect_request, 0, sizeof(std::set<RawAddress>)); memset(®1.mtu_prefs, 0, sizeof(std::map<RawAddress, uint16_t>)); reg1 = {}; ASSERT_EQ(0, memcmp(reg0.get(), ®1, actual_sizeof_tGATT_REG())); diff --git a/system/stack/test/rfcomm/stack_rfcomm_port_test.cc b/system/stack/test/rfcomm/stack_rfcomm_port_test.cc index 54ca9943b6..084e109c72 100644 --- a/system/stack/test/rfcomm/stack_rfcomm_port_test.cc +++ b/system/stack/test/rfcomm/stack_rfcomm_port_test.cc @@ -48,9 +48,9 @@ TEST_F(StackRfcommPortTest, PORT_IsOpening__basic) { ASSERT_TRUE(PORT_IsOpening(&bd_addr)); rfc_cb.port.rfc_mcb[0].state = RFC_MX_STATE_CONNECTED; rfc_cb.port.port[0].rfc.p_mcb = &rfc_cb.port.rfc_mcb[0]; - rfc_cb.port.port[0].rfc.state = RFC_STATE_OPENED; + rfc_cb.port.port[0].rfc.sm_cb.state = RFC_STATE_OPENED; ASSERT_FALSE(PORT_IsOpening(&bd_addr)); - rfc_cb.port.port[0].rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK; + rfc_cb.port.port[0].rfc.sm_cb.state = RFC_STATE_TERM_WAIT_SEC_CHECK; ASSERT_TRUE(PORT_IsOpening(&bd_addr)); rfc_cb.port.rfc_mcb[0].state = RFC_MX_STATE_DISC_WAIT_UA; ASSERT_FALSE(PORT_IsOpening(&bd_addr)); @@ -90,9 +90,9 @@ TEST_F(StackRfcommPortTest, PORT_IsCollisionDetected__basic) { rfc_cb.port.rfc_mcb[0].state = RFC_MX_STATE_CONNECTED; rfc_cb.port.port[0].rfc.p_mcb = &rfc_cb.port.rfc_mcb[0]; - rfc_cb.port.port[0].rfc.state = RFC_STATE_OPENED; + rfc_cb.port.port[0].rfc.sm_cb.state = RFC_STATE_OPENED; ASSERT_FALSE(PORT_IsCollisionDetected(test_bd_addr)); - rfc_cb.port.port[0].rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK; + rfc_cb.port.port[0].rfc.sm_cb.state = RFC_STATE_TERM_WAIT_SEC_CHECK; ASSERT_TRUE(PORT_IsCollisionDetected(test_bd_addr)); rfc_cb.port.rfc_mcb[0].state = RFC_MX_STATE_DISC_WAIT_UA; ASSERT_FALSE(PORT_IsCollisionDetected(test_bd_addr)); diff --git a/system/test/Android.bp b/system/test/Android.bp index c5a3b0c2d6..595f148754 100644 --- a/system/test/Android.bp +++ b/system/test/Android.bp @@ -205,7 +205,6 @@ filegroup { filegroup { name: "TestMockMainShim", srcs: [ - "mock/mock_main_shim.cc", "mock/mock_main_shim_BtifConfigInterface.cc", "mock/mock_main_shim_acl.cc", "mock/mock_main_shim_acl_api.cc", @@ -363,19 +362,11 @@ filegroup { filegroup { name: "TestMockMainShimLeScanning", srcs: [ - "mock/mock_main_shim.cc", "mock/mock_main_shim_le_scanning_manager.cc", ], } filegroup { - name: "TestMockMainShimFlags", - srcs: [ - "mock/mock_main_shim.cc", - ], -} - -filegroup { name: "TestMockBtif", srcs: [ ":TestCommonCoreInterface", diff --git a/system/test/mock/mock_bta_jv_api.cc b/system/test/mock/mock_bta_jv_api.cc index ec913b5b01..52f8ffcabe 100644 --- a/system/test/mock/mock_bta_jv_api.cc +++ b/system/test/mock/mock_bta_jv_api.cc @@ -76,14 +76,16 @@ tBTA_JV_STATUS BTA_JvRfcommClose(uint32_t /* handle */, uint32_t /* rfcomm_slot_ tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC /* sec_mask */, uint8_t /* remote_scn */, const RawAddress& /* peer_bd_addr */, tBTA_JV_RFCOMM_CBACK* /* p_cback */, - uint32_t /* rfcomm_slot_id */, RfcommCfgInfo /* cfg */) { + uint32_t /* rfcomm_slot_id */, RfcommCfgInfo /* cfg */, + uint32_t /* app_uid */) { inc_func_call_count(__func__); return tBTA_JV_STATUS::SUCCESS; } tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC /* sec_mask */, uint8_t /* local_scn */, uint8_t /* max_session */, tBTA_JV_RFCOMM_CBACK* /* p_cback */, - uint32_t /* rfcomm_slot_id */, RfcommCfgInfo /* cfg */) { + uint32_t /* rfcomm_slot_id */, RfcommCfgInfo /* cfg */, + uint32_t /* app_uid */) { inc_func_call_count(__func__); return tBTA_JV_STATUS::SUCCESS; } diff --git a/system/test/mock/mock_bta_leaudio.cc b/system/test/mock/mock_bta_leaudio.cc index 2b5aeb8ff9..24824032a3 100644 --- a/system/test/mock/mock_bta_leaudio.cc +++ b/system/test/mock/mock_bta_leaudio.cc @@ -41,14 +41,12 @@ class HalVersionManager { } // namespace audio } // namespace bluetooth -void LeAudioClient::AddFromStorage(const RawAddress& /* addr */, bool /* autoconnect */, - int /* sink_audio_location */, int /* source_audio_location */, - int /* sink_supported_context_types */, - int /* source_supported_context_types */, - const std::vector<uint8_t>& /* handles */, - const std::vector<uint8_t>& /* sink_pacs */, - const std::vector<uint8_t>& /* source_pacs */, - const std::vector<uint8_t>& /* ases */) { +void LeAudioClient::AddFromStorage( + const RawAddress& /* addr */, bool /* autoconnect */, int /* sink_audio_location */, + int /* source_audio_location */, int /* sink_supported_context_types */, + int /* source_supported_context_types */, const std::vector<uint8_t>& /* handles */, + const std::vector<uint8_t>& /* sink_pacs */, const std::vector<uint8_t>& /* source_pacs */, + const std::vector<uint8_t>& /* ases */, const std::vector<uint8_t>& /* gmap */) { inc_func_call_count(__func__); } @@ -76,6 +74,12 @@ bool LeAudioClient::GetAsesForStorage(const RawAddress& /* addr */, return false; } +bool LeAudioClient::GetGmapForStorage(const RawAddress& /* addr */, + std::vector<uint8_t>& /* out */) { + inc_func_call_count(__func__); + return false; +} + void LeAudioClient::Cleanup(void) { inc_func_call_count(__func__); } LeAudioClient* LeAudioClient::Get(void) { diff --git a/system/test/mock/mock_btif_profile_storage.cc b/system/test/mock/mock_btif_profile_storage.cc index a89422a7ee..a65103fa8e 100644 --- a/system/test/mock/mock_btif_profile_storage.cc +++ b/system/test/mock/mock_btif_profile_storage.cc @@ -55,6 +55,7 @@ struct btif_storage_leaudio_clear_service_data btif_storage_leaudio_clear_servic struct btif_storage_leaudio_update_ase_bin btif_storage_leaudio_update_ase_bin; struct btif_storage_leaudio_update_handles_bin btif_storage_leaudio_update_handles_bin; struct btif_storage_leaudio_update_pacs_bin btif_storage_leaudio_update_pacs_bin; +struct btif_storage_leaudio_update_gmap_bin btif_storage_leaudio_update_gmap_bin; struct btif_storage_load_bonded_csis_devices btif_storage_load_bonded_csis_devices; struct btif_storage_load_bonded_groups btif_storage_load_bonded_groups; struct btif_storage_load_bonded_hearing_aids btif_storage_load_bonded_hearing_aids; @@ -183,6 +184,10 @@ void btif_storage_leaudio_update_pacs_bin(const RawAddress& addr) { inc_func_call_count(__func__); test::mock::btif_profile_storage::btif_storage_leaudio_update_pacs_bin(addr); } +void btif_storage_leaudio_update_gmap_bin(const RawAddress& addr) { + inc_func_call_count(__func__); + test::mock::btif_profile_storage::btif_storage_leaudio_update_gmap_bin(addr); +} void btif_storage_load_bonded_csis_devices(void) { inc_func_call_count(__func__); test::mock::btif_profile_storage::btif_storage_load_bonded_csis_devices(); diff --git a/system/test/mock/mock_btif_profile_storage.h b/system/test/mock/mock_btif_profile_storage.h index 7d322e543d..1d0bbd7c96 100644 --- a/system/test/mock/mock_btif_profile_storage.h +++ b/system/test/mock/mock_btif_profile_storage.h @@ -226,6 +226,15 @@ struct btif_storage_leaudio_update_pacs_bin { }; extern struct btif_storage_leaudio_update_pacs_bin btif_storage_leaudio_update_pacs_bin; +// Name: btif_storage_leaudio_update_gmap_bin +// Params: void +// Return: void +struct btif_storage_leaudio_update_gmap_bin { + std::function<void(const RawAddress& addr)> body{[](const RawAddress& /* addr */) {}}; + void operator()(const RawAddress& addr) { body(addr); } +}; +extern struct btif_storage_leaudio_update_gmap_bin btif_storage_leaudio_update_gmap_bin; + // Name: btif_storage_load_bonded_csis_devices // Params: void // Return: void diff --git a/system/test/mock/mock_main_shim.cc b/system/test/mock/mock_main_shim.cc deleted file mode 100644 index 8e26aaeecd..0000000000 --- a/system/test/mock/mock_main_shim.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Generated mock file from original source file - * Functions generated:14 - */ - -#define LOG_TAG "bt_shim" - -#include "main/shim/shim.h" -#include "test/common/mock_functions.h" - -namespace test { -namespace mock { -bool bluetooth_shim_is_gd_stack_started_up = false; -} -} // namespace test -bool bluetooth::shim::is_gd_stack_started_up() { - inc_func_call_count(__func__); - return test::mock::bluetooth_shim_is_gd_stack_started_up; -} diff --git a/system/test/mock/mock_main_shim_entry.cc b/system/test/mock/mock_main_shim_entry.cc index 291cb0c0fd..a78ff5bdf5 100644 --- a/system/test/mock/mock_main_shim_entry.cc +++ b/system/test/mock/mock_main_shim_entry.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "test/mock/mock_main_shim_entry.h" + #include "hci/acl_manager_mock.h" #include "hci/controller_interface_mock.h" #include "hci/distance_measurement_manager_mock.h" @@ -22,9 +24,16 @@ #include "hci/le_scanning_manager_mock.h" #include "lpp/lpp_offload_interface_mock.h" #include "main/shim/entry.h" +#include "main/shim/shim.h" #include "os/handler.h" #include "storage/storage_module.h" +namespace test { +namespace mock { +bool bluetooth_shim_is_gd_stack_started_up = false; +} // namespace mock +} // namespace test + namespace bluetooth { namespace hci { namespace testing { @@ -65,6 +74,7 @@ hci::RemoteNameRequestModule* GetRemoteNameRequest() { return nullptr; } lpp::LppOffloadInterface* GetLppOffloadManager() { return lpp::testing::mock_lpp_offload_interface_; } +bool is_gd_stack_started_up() { return test::mock::bluetooth_shim_is_gd_stack_started_up; } } // namespace shim } // namespace bluetooth diff --git a/system/test/mock/mock_stack_gatt_main.cc b/system/test/mock/mock_stack_gatt_main.cc index 2c09b4a768..ead90a71d1 100644 --- a/system/test/mock/mock_stack_gatt_main.cc +++ b/system/test/mock/mock_stack_gatt_main.cc @@ -33,9 +33,6 @@ bool gatt_act_connect(tGATT_REG* /* p_reg */, const RawAddress& /* bd_addr */, inc_func_call_count(__func__); return false; } -void gatt_cancel_connect(const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport*/) { - inc_func_call_count(__func__); -} bool gatt_disconnect(tGATT_TCB* /* p_tcb */) { inc_func_call_count(__func__); return false; diff --git a/system/test/mock/mock_stack_rfcomm_port_api.cc b/system/test/mock/mock_stack_rfcomm_port_api.cc index b87a752689..388f0cbdfc 100644 --- a/system/test/mock/mock_stack_rfcomm_port_api.cc +++ b/system/test/mock/mock_stack_rfcomm_port_api.cc @@ -115,3 +115,7 @@ bool PORT_IsCollisionDetected(RawAddress /* bd_addr */) { inc_func_call_count(__func__); return false; } +int PORT_SetAppUid(uint16_t /* handle */, uint32_t /* app_uid */) { + inc_func_call_count(__func__); + return 0; +} diff --git a/system/types/Android.bp b/system/types/Android.bp index 00a0de546d..e00941d8ec 100644 --- a/system/types/Android.bp +++ b/system/types/Android.bp @@ -15,7 +15,7 @@ cc_library_headers { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", "com.android.media", "com.android.media.swcodec", ], @@ -45,7 +45,7 @@ cc_library_static { export_header_lib_headers: ["libbluetooth-types-header"], apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "29", } diff --git a/system/udrv/Android.bp b/system/udrv/Android.bp index 5a69d8e886..fb77f0f0f1 100644 --- a/system/udrv/Android.bp +++ b/system/udrv/Android.bp @@ -24,7 +24,7 @@ cc_library_static { host_supported: true, apex_available: [ "//apex_available:platform", - "com.android.btservices", + "com.android.bt", ], min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], |