Merge changes I838a8a65,I51112332 into main
* changes:
SystemServer: remove avoid_static_loading_of_native
SystemServer: remove fast_bind_to_app
diff --git a/.clang-tidy b/.clang-tidy
index df0d649..9dc029b 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,4 +1,18 @@
---
CheckOptions:
- - key: misc-include-cleaner.IgnoreHeaders
- value: (fmt/.*|bits/pthread_types\.h)
+ - key: misc-include-cleaner.IgnoreHeaders
+ value: "(\
+ fmt/.*|\
+ bits/.*.h|\
+ asm-generic/.*.h|\
+ sys/poll.h|\
+ sys/endian.h|\
+ sys/ioctl.h|\
+ arpa/inet.h|\
+ linux/if.h|\
+ linux/sockios.h|\
+ netinet/in.h|\
+ osi/include/compat.h|\
+ android_bluetooth_sysprop.h|\
+ hfp.sysprop.h|\
+ __chrono/duration.h)"
diff --git a/Android.bp b/Android.bp
index 71d6d40..476d018 100644
--- a/Android.bp
+++ b/Android.bp
@@ -85,6 +85,11 @@
// This check implements detection of local variables which could be declared
// as const but are not.
"-misc-const-correctness",
+
+ // Finds classes that contain non-static data members in addition to user-declared
+ // non-static member functions and diagnose all data members declared with a
+ // non-public access specifier.
+ "-misc-non-private-member-variables-in-classes",
]
// This default tidy checks that will be run against all the cc targets
@@ -165,6 +170,7 @@
"-Xep:UnusedMethod:ERROR",
"-Xep:UnusedNestedClass:ERROR",
"-Xep:UnusedVariable:ERROR",
+ "-Xep:VariableNameSameAsType:ERROR",
"-Xep:WaitNotInLoop:ERROR",
"-Xep:WakelockReleasedDangerously:ERROR",
@@ -172,8 +178,8 @@
"-XepExcludedPaths:.*/srcjars/.*",
// The @InlineMe annotation could be made available, but it would
- // apply on external facing API. This is not desired. For more
- // context, see https://r.android.com/3303475
+ // apply on external facing API. This is not desired.
+ // For more context, see https://r.android.com/3303475
"-Xep:InlineMeSuggester:OFF",
],
},
diff --git a/OWNERS b/OWNERS
index 4df6c99..491c4d0 100644
--- a/OWNERS
+++ b/OWNERS
@@ -9,7 +9,7 @@
# Per-file ownership
# Build files / test_config / presubmit / preupload / linter file
-per-file PREUPLOAD.cfg,TEST_MAPPING,*.bp,*.xml,pyrightconfig.json=file:/OWNERS_build
+per-file PREUPLOAD.cfg,TEST_MAPPING,*.bp,*.xml,.clang-tidy,pyrightconfig.json=file:/OWNERS_build
# ChromeOS team owns Linux build files
# - build.py is used for Linux build
diff --git a/OWNERS_hearingaid b/OWNERS_hearingaid
index e70772a..d1c75de 100644
--- a/OWNERS_hearingaid
+++ b/OWNERS_hearingaid
@@ -1 +1 @@
-charliebout@google.com
+henrichataing@google.com
diff --git a/android/app/Android.bp b/android/app/Android.bp
index 2bac3ba..d4fccc0 100644
--- a/android/app/Android.bp
+++ b/android/app/Android.bp
@@ -73,6 +73,9 @@
"jni_headers",
"libbluetooth_headers",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
include_dirs: [
"packages/modules/Bluetooth/system",
"packages/modules/Bluetooth/system/gd",
@@ -88,6 +91,7 @@
// is required to maintain FIPS compliance.
stl: "libc++_static",
static_libs: [
+ "aics",
"android.hardware.audio.common@5.0",
"android.hardware.bluetooth.audio@2.0",
"android.hardware.bluetooth.audio@2.1",
@@ -267,6 +271,7 @@
"bluetooth-protos-lite",
"bluetooth.change-ids",
"bluetooth.mapsapi",
+ "bluetooth_constants_java",
"com.android.obex",
"com.android.vcard",
"guava",
diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl
index bf95bb5..54b947c 100644
--- a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl
+++ b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl
@@ -60,4 +60,6 @@
List<BluetoothLeBroadcastReceiveState> getAllSources(in BluetoothDevice sink, in AttributionSource source);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
int getMaximumSourceCapacity(in BluetoothDevice sink, in AttributionSource source);
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
+ BluetoothLeBroadcastMetadata getSourceMetadata(in BluetoothDevice sink, in int sourceId, in AttributionSource source);
}
diff --git a/android/app/jni/com_android_bluetooth_vc.cpp b/android/app/jni/com_android_bluetooth_vc.cpp
index 39bd355..e7cf0ab 100644
--- a/android/app/jni/com_android_bluetooth_vc.cpp
+++ b/android/app/jni/com_android_bluetooth_vc.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "BluetoothVolumeControlServiceJni"
+#include <aics/api.h>
#include <bluetooth/log.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
@@ -34,9 +35,12 @@
#include "hardware/bt_vc.h"
#include "types/raw_address.h"
+using bluetooth::aics::Mute;
using bluetooth::vc::ConnectionState;
using bluetooth::vc::VolumeControlCallbacks;
using bluetooth::vc::VolumeControlInterface;
+using bluetooth::vc::VolumeInputStatus;
+using bluetooth::vc::VolumeInputType;
namespace android {
static jmethodID method_onConnectionStateChanged;
@@ -58,6 +62,8 @@
static jobject mCallbacksObj = nullptr;
static std::shared_timed_mutex callbacks_mutex;
+static jfieldID sCallbacksField;
+
class VolumeControlCallbacksImpl : public VolumeControlCallbacks {
public:
~VolumeControlCallbacksImpl() = default;
@@ -217,8 +223,8 @@
(jint)ext_output_id, description, addr.get());
}
- void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id, int8_t gain_val,
- uint8_t gain_mode, bool mute) override {
+ void OnExtAudioInStateChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
+ int8_t gain_setting, Mute mute, uint8_t gain_mode) override {
log::info("");
std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -237,11 +243,11 @@
sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
reinterpret_cast<const jbyte*>(&bd_addr));
sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExtAudioInStateChanged, (jint)ext_input_id,
- (jint)gain_val, (jint)gain_mode, (jboolean)mute, addr.get());
+ (jint)gain_setting, (jint)mute, (jint)gain_mode, addr.get());
}
void OnExtAudioInStatusChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
- bluetooth::vc::VolumeInputStatus status) override {
+ VolumeInputStatus status) override {
log::info("");
std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -264,7 +270,7 @@
}
void OnExtAudioInTypeChanged(const RawAddress& bd_addr, uint8_t ext_input_id,
- bluetooth::vc::VolumeInputType type) override {
+ VolumeInputType type) override {
log::info("");
std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
@@ -358,7 +364,8 @@
mCallbacksObj = nullptr;
}
- if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
+ if ((mCallbacksObj = env->NewGlobalRef(env->GetObjectField(object, sCallbacksField))) ==
+ nullptr) {
log::error("Failed to allocate Global Ref for Volume control Callbacks");
return;
}
@@ -775,8 +782,9 @@
return JNI_TRUE;
}
-static jboolean setExtAudioInGainValueNative(JNIEnv* env, jobject /* object */, jbyteArray address,
- jint ext_input_id, jint gain_val) {
+static jboolean setExtAudioInGainSettingNative(JNIEnv* env, jobject /* object */,
+ jbyteArray address, jint ext_input_id,
+ jint gain_setting) {
log::info("");
std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
if (!sVolumeControlInterface) {
@@ -790,7 +798,7 @@
}
RawAddress* tmpraw = reinterpret_cast<RawAddress*>(addr);
- sVolumeControlInterface->SetExtAudioInGainValue(*tmpraw, ext_input_id, gain_val);
+ sVolumeControlInterface->SetExtAudioInGainSetting(*tmpraw, ext_input_id, gain_setting);
env->ReleaseByteArrayElements(address, addr, 0);
return JNI_TRUE;
}
@@ -871,8 +879,8 @@
reinterpret_cast<void*>(getExtAudioInDescriptionNative)},
{"setExtAudioInDescriptionNative", "([BILjava/lang/String;)Z",
reinterpret_cast<void*>(setExtAudioInDescriptionNative)},
- {"setExtAudioInGainValueNative", "([BII)Z",
- reinterpret_cast<void*>(setExtAudioInGainValueNative)},
+ {"setExtAudioInGainSettingNative", "([BII)Z",
+ reinterpret_cast<void*>(setExtAudioInGainSettingNative)},
{"setExtAudioInGainModeNative", "([BIZ)Z",
reinterpret_cast<void*>(setExtAudioInGainModeNative)},
{"setExtAudioInGainMuteNative", "([BIZ)Z",
@@ -884,6 +892,12 @@
return result;
}
+ jclass jniVolumeControlNativeInterfaceClass =
+ env->FindClass("com/android/bluetooth/vc/VolumeControlNativeInterface");
+ sCallbacksField = env->GetFieldID(jniVolumeControlNativeInterfaceClass, "mNativeCallback",
+ "Lcom/android/bluetooth/vc/VolumeControlNativeCallback;");
+ env->DeleteLocalRef(jniVolumeControlNativeInterfaceClass);
+
const JNIJavaMethod javaMethods[] = {
{"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged},
{"onVolumeStateChanged", "(IZI[BZ)V", &method_onVolumeStateChanged},
@@ -893,14 +907,14 @@
{"onExtAudioOutLocationChanged", "(II[B)V", &method_onExtAudioOutLocationChanged},
{"onExtAudioOutDescriptionChanged", "(ILjava/lang/String;[B)V",
&method_onExtAudioOutDescriptionChanged},
- {"onExtAudioInStateChanged", "(IIIZ[B)V", &method_onExtAudioInStateChanged},
+ {"onExtAudioInStateChanged", "(IIII[B)V", &method_onExtAudioInStateChanged},
{"onExtAudioInStatusChanged", "(II[B)V", &method_onExtAudioInStatusChanged},
{"onExtAudioInTypeChanged", "(II[B)V", &method_onExtAudioInTypeChanged},
{"onExtAudioInGainPropsChanged", "(IIII[B)V", &method_onExtAudioInGainPropsChanged},
{"onExtAudioInDescriptionChanged", "(ILjava/lang/String;[B)V",
&method_onExtAudioInDescriptionChanged},
};
- GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeInterface", javaMethods);
+ GET_JAVA_METHODS(env, "com/android/bluetooth/vc/VolumeControlNativeCallback", javaMethods);
return 0;
}
diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml
index 1b2c4fe..c972c11 100644
--- a/android/app/lint-baseline.xml
+++ b/android/app/lint-baseline.xml
@@ -371,7 +371,7 @@
errorLine2=" ^">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java"
- line="734"
+ line="672"
column="9"/>
</issue>
@@ -382,7 +382,7 @@
errorLine2=" ^">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java"
- line="734"
+ line="672"
column="9"/>
</issue>
@@ -393,7 +393,7 @@
errorLine2=" ^">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java"
- line="734"
+ line="672"
column="9"/>
</issue>
@@ -448,7 +448,7 @@
errorLine2=" ^">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java"
- line="918"
+ line="922"
column="9"/>
</issue>
@@ -547,7 +547,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java"
- line="673"
+ line="642"
column="31"/>
</issue>
@@ -558,7 +558,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java"
- line="847"
+ line="816"
column="33"/>
</issue>
@@ -569,7 +569,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java"
- line="855"
+ line="824"
column="26"/>
</issue>
@@ -580,7 +580,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java"
- line="868"
+ line="837"
column="33"/>
</issue>
@@ -591,18 +591,18 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java"
- line="888"
+ line="857"
column="26"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.sendMessage(A2dpStateMachine.STACK_EVENT, stackEvent);"
- errorLine2=" ~~~~~~~~~~~">
+ errorLine1=" sm.sendMessage(A2dpStateMachine.MESSAGE_STACK_EVENT, stackEvent);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java"
- line="963"
+ line="929"
column="45"/>
</issue>
@@ -613,7 +613,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java"
- line="477"
+ line="493"
column="31"/>
</issue>
@@ -624,7 +624,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="1190"
+ line="1173"
column="20"/>
</issue>
@@ -635,7 +635,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="1195"
+ line="1178"
column="20"/>
</issue>
@@ -646,7 +646,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="2025"
+ line="2024"
column="43"/>
</issue>
@@ -657,7 +657,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="2030"
+ line="2029"
column="45"/>
</issue>
@@ -668,7 +668,7 @@
errorLine2=" ~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="2034"
+ line="2033"
column="34"/>
</issue>
@@ -679,7 +679,7 @@
errorLine2=" ~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="2266"
+ line="2265"
column="33"/>
</issue>
@@ -690,7 +690,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="6876"
+ line="6885"
column="28"/>
</issue>
@@ -701,7 +701,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="6878"
+ line="6887"
column="28"/>
</issue>
@@ -1015,980 +1015,23 @@
<issue
id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" private final Map<BluetoothDevice, BassClientStateMachine> mStateMachines = new HashMap<>();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="148"
- column="40"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" .anyMatch(e -> e.first.equals(BassClientStateMachine.ADD_BCAST_SOURCE));"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="852"
- column="82"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" case BassClientStateMachine.ADD_BCAST_SOURCE:"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="878"
- column="41"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" .ADD_BCAST_SOURCE))"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="891"
- column="70"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" (m.first.equals(BassClientStateMachine.ADD_BCAST_SOURCE))"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="903"
- column="76"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" case BassClientStateMachine.REMOVE_BCAST_SOURCE:"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="921"
- column="41"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" m.first.equals(BassClientStateMachine.REMOVE_BCAST_SOURCE)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="926"
- column="71"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="969"
- column="17"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" && (sm.hasPendingSwitchingSourceOperation()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="973"
- column="32"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" || sm.hasPendingSourceOperation())) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="974"
- column="39"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1136"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.getCurrentBroadcastMetadata(sourceId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1144"
- column="34"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" getOrCreateStateMachine(device).getAllSources();"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1150"
- column="61"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = null;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1227"
- column="9"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" for (BluetoothLeBroadcastReceiveState recvState : stateMachine.getAllSources()) {"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1236"
- column="72"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = null;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1247"
- column="9"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" List<BluetoothLeBroadcastReceiveState> sources = stateMachine.getAllSources();"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1256"
- column="71"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" private BassClientStateMachine getOrCreateStateMachine(BluetoothDevice device) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1281"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = mStateMachines.get(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1287"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = mStateMachines.get(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1359"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.doQuit();"
- errorLine2=" ~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1367"
- column="16"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.cleanup();"
- errorLine2=" ~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1368"
- column="16"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1404"
- column="17"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.sendMessage(BassClientStateMachine.STOP_SCAN_OFFLOAD);"
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1413"
- column="65"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1420"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (stateMachine.hasPendingSourceOperation()) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1449"
- column="26"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1559"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.sendMessage(BassClientStateMachine.CONNECT);"
- errorLine2=" ~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1565"
- column="61"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1583"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.sendMessage(BassClientStateMachine.DISCONNECT);"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1589"
- column="61"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1633"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" return sm.getConnectionState();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1638"
- column="23"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1664"
- column="17"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" connectionState = sm.getConnectionState();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1666"
- column="42"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (sm.isConnected()) {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1688"
- column="24"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" devices.add(sm.getDevice());"
- errorLine2=" ~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1689"
- column="36"/>
- </issue>
-
- <issue
- id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
errorLine1=" mDatabaseManager.setProfileConnectionPolicy("
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1711"
+ line="1822"
column="34"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (sm.isConnected()) {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1850"
- column="56"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" selectSource(sm.getDevice(), result, false);"
- errorLine2=" ~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1851"
- column="69"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1903"
- column="21"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.sendMessage(BassClientStateMachine.START_SCAN_OFFLOAD);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="1912"
- column="69"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2639"
- column="17"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.REACHED_MAX_SOURCE_LIMIT);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2645"
- column="75"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2655"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.SELECT_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2661"
- column="71"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2776"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (stateMachine.hasPendingSourceOperation()) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2789"
- column="30"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.getCurrentBroadcastMetadata(sourceId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2805"
- column="42"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" device, BassClientStateMachine.REMOVE_BCAST_SOURCE, sourceId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2828"
- column="64"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata);"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2830"
- column="64"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.SWITCH_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2837"
- column="79"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" device, BassClientStateMachine.ADD_BCAST_SOURCE, sourceMetadata);"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2874"
- column="56"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" Message message = stateMachine.obtainMessage(BassClientStateMachine.ADD_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2889"
- column="81"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE);"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2900"
- column="77"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" message.arg1 = BassClientStateMachine.ARGTYPE_METADATA;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2902"
- column="55"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2940"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2959"
- column="71"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" message = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE);"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2973"
- column="77"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" message.arg1 = BassClientStateMachine.ARGTYPE_METADATA;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2975"
- column="55"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="2994"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.getCurrentBroadcastMetadata(sourceId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3023"
- column="34"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (metaData != null && stateMachine.isSyncedToTheSource(sourceId)) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3029"
- column="50"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3040"
- column="75"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.REMOVE_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3054"
- column="71"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine.REMOVE_BCAST_SOURCE,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3064"
- column="44"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3078"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" return stateMachine.getAllSources().stream()"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3083"
- column="33"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3097"
- column="9"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" return stateMachine.getMaximumSourceCapacity();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3102"
- column="29"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = getOrCreateStateMachine(device);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3167"
- column="17"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (sm != null && sm.hasPendingSourceOperation(broadcastId)) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3168"
- column="38"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine.CANCEL_PENDING_SOURCE_OPERATION);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3171"
- column="60"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" getOrCreateStateMachine(groupDevice).getAllSources().stream()"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3417"
- column="58"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3580"
- column="17"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" List<BluetoothLeBroadcastReceiveState> sources = stateMachine.getAllSources();"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3581"
- column="79"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3617"
- column="79"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" sink, reason, BassClientStateMachine.ADD_BCAST_SOURCE, param.mObj2);"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3876"
- column="66"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine.REMOVE_BCAST_SOURCE,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="3884"
- column="52"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = entry.getValue();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="4192"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="4193"
- column="20"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.dump(sb);"
- errorLine2=" ~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="4194"
- column="20"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine sm = entry.getValue();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="4201"
- column="13"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" if (sm.getConnectionState() != BluetoothProfile.STATE_CONNECTED) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="4202"
- column="20"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.dump(sb);"
- errorLine2=" ~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassClientService.java"
- line="4203"
- column="20"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" public BassClientStateMachine makeStateMachine("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java"
- line="73"
- column="12"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" return BassClientStateMachine.make(device, svc, adapterService, looper);"
- errorLine2=" ~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java"
- line="78"
- column="39"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This class should only be accessed from tests or within private scope"
- errorLine1=" public void destroyStateMachine(BassClientStateMachine stateMachine) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java"
- line="86"
- column="37"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" BassClientStateMachine.destroy(stateMachine);"
- errorLine2=" ~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bass_client/BassObjectsFactory.java"
- line="87"
- column="32"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" mDatabaseManager.setProfileConnectionPolicy("
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/bas/BatteryService.java"
- line="353"
+ line="325"
column="26"/>
</issue>
@@ -4078,7 +3121,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java"
- line="449"
+ line="454"
column="26"/>
</issue>
@@ -4089,7 +3132,7 @@
errorLine2=" ~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java"
- line="879"
+ line="884"
column="63"/>
</issue>
@@ -4892,7 +3935,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1214"
+ line="1213"
column="29"/>
</issue>
@@ -4903,7 +3946,7 @@
errorLine2=" ~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1227"
+ line="1226"
column="39"/>
</issue>
@@ -4914,7 +3957,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1228"
+ line="1227"
column="66"/>
</issue>
@@ -4925,7 +3968,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1235"
+ line="1234"
column="29"/>
</issue>
@@ -4936,7 +3979,7 @@
errorLine2=" ~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1237"
+ line="1236"
column="35"/>
</issue>
@@ -4947,7 +3990,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1238"
+ line="1237"
column="55"/>
</issue>
@@ -4958,7 +4001,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1324"
+ line="1323"
column="13"/>
</issue>
@@ -4969,7 +4012,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1324"
+ line="1323"
column="29"/>
</issue>
@@ -4980,7 +4023,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1325"
+ line="1324"
column="18"/>
</issue>
@@ -4991,7 +4034,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1326"
+ line="1325"
column="18"/>
</issue>
@@ -5002,7 +4045,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1327"
+ line="1326"
column="18"/>
</issue>
@@ -5013,7 +4056,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1328"
+ line="1327"
column="18"/>
</issue>
@@ -5024,7 +4067,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1330"
+ line="1329"
column="18"/>
</issue>
@@ -5035,7 +4078,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1331"
+ line="1330"
column="18"/>
</issue>
@@ -5046,7 +4089,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1332"
+ line="1331"
column="18"/>
</issue>
@@ -5057,7 +4100,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1333"
+ line="1332"
column="18"/>
</issue>
@@ -5068,7 +4111,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1335"
+ line="1334"
column="18"/>
</issue>
@@ -5079,7 +4122,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1336"
+ line="1335"
column="18"/>
</issue>
@@ -5090,6 +4133,17 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
+ line="1336"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" data.setProfileConnectionPolicy("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
line="1337"
column="18"/>
</issue>
@@ -5101,18 +4155,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1338"
- column="18"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" data.setProfileConnectionPolicy("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1340"
+ line="1339"
column="18"/>
</issue>
@@ -5123,7 +4166,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1342"
+ line="1341"
column="18"/>
</issue>
@@ -5134,7 +4177,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1343"
+ line="1342"
column="18"/>
</issue>
@@ -5145,7 +4188,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1349"
+ line="1348"
column="9"/>
</issue>
@@ -5156,7 +4199,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1349"
+ line="1348"
column="30"/>
</issue>
@@ -5167,7 +4210,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1350"
+ line="1349"
column="19"/>
</issue>
@@ -5178,7 +4221,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1433"
+ line="1432"
column="33"/>
</issue>
@@ -5189,7 +4232,7 @@
errorLine2=" ~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1434"
+ line="1433"
column="18"/>
</issue>
@@ -5200,7 +4243,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1438"
+ line="1437"
column="45"/>
</issue>
@@ -5211,7 +4254,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1498"
+ line="1497"
column="36"/>
</issue>
@@ -5222,7 +4265,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java"
- line="1502"
+ line="1501"
column="52"/>
</issue>
@@ -5585,7 +4628,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="253"
+ line="273"
column="38"/>
</issue>
@@ -5596,7 +4639,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="255"
+ line="275"
column="42"/>
</issue>
@@ -5607,7 +4650,7 @@
errorLine2=" ~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="268"
+ line="288"
column="26"/>
</issue>
@@ -5618,7 +4661,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="421"
+ line="441"
column="42"/>
</issue>
@@ -5629,7 +4672,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="489"
+ line="509"
column="30"/>
</issue>
@@ -5640,7 +4683,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="889"
+ line="909"
column="48"/>
</issue>
@@ -5651,7 +4694,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="937"
+ line="957"
column="48"/>
</issue>
@@ -5662,7 +4705,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="957"
+ line="977"
column="34"/>
</issue>
@@ -5673,7 +4716,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="958"
+ line="978"
column="46"/>
</issue>
@@ -5684,7 +4727,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1005"
+ line="1025"
column="33"/>
</issue>
@@ -5695,7 +4738,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1033"
+ line="1053"
column="31"/>
</issue>
@@ -5706,7 +4749,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1119"
+ line="1139"
column="38"/>
</issue>
@@ -5717,7 +4760,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1121"
+ line="1141"
column="42"/>
</issue>
@@ -5728,18 +4771,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1137"
- column="48"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" AudioManager am = mSystemInterface.getAudioManager();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1163"
+ line="1157"
column="48"/>
</issue>
@@ -5750,51 +4782,29 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1211"
+ line="1231"
column="48"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" mSystemInterface.getAudioManager().clearCommunicationDevice();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1232"
- column="42"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" mNativeInterface.setScoAllowed(allowed);"
errorLine2=" ~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1266"
+ line="1286"
column="26"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" .getAudioManager()"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1402"
- column="22"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" mNativeInterface.setActiveDevice(null);"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1410"
+ line="1421"
column="30"/>
</issue>
@@ -5805,7 +4815,7 @@
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1443"
+ line="1464"
column="35"/>
</issue>
@@ -5816,7 +4826,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1454"
+ line="1475"
column="34"/>
</issue>
@@ -5827,7 +4837,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1454"
+ line="1475"
column="65"/>
</issue>
@@ -5838,62 +4848,29 @@
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1472"
+ line="1493"
column="38"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" .getAudioManager()"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1478"
- column="30"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" .getAudioManager()"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1492"
- column="30"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" mNativeInterface.setActiveDevice(previousActiveDevice);"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1515"
+ line="1535"
column="42"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" .getAudioManager()"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1523"
- column="30"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" if (stateMachine.getConnectionState() != BluetoothProfile.STATE_CONNECTED) {"
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1573"
+ line="1594"
column="30"/>
</issue>
@@ -5904,7 +4881,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1598"
+ line="1619"
column="46"/>
</issue>
@@ -5915,7 +4892,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1808"
+ line="1829"
column="38"/>
</issue>
@@ -5926,7 +4903,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1810"
+ line="1831"
column="42"/>
</issue>
@@ -5937,7 +4914,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1892"
+ line="1913"
column="35"/>
</issue>
@@ -5948,7 +4925,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1905"
+ line="1926"
column="35"/>
</issue>
@@ -5959,7 +4936,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1906"
+ line="1927"
column="34"/>
</issue>
@@ -5970,7 +4947,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1933"
+ line="1954"
column="38"/>
</issue>
@@ -5981,7 +4958,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1935"
+ line="1956"
column="42"/>
</issue>
@@ -5992,7 +4969,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="1956"
+ line="1977"
column="35"/>
</issue>
@@ -6003,7 +4980,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2103"
+ line="2124"
column="48"/>
</issue>
@@ -6014,7 +4991,7 @@
errorLine2=" ~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2251"
+ line="2272"
column="86"/>
</issue>
@@ -6025,7 +5002,7 @@
errorLine2=" ~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2259"
+ line="2280"
column="52"/>
</issue>
@@ -6036,7 +5013,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2287"
+ line="2308"
column="33"/>
</issue>
@@ -6047,7 +5024,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2288"
+ line="2309"
column="38"/>
</issue>
@@ -6058,7 +5035,7 @@
errorLine2=" ~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2429"
+ line="2539"
column="56"/>
</issue>
@@ -6069,7 +5046,7 @@
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2494"
+ line="2604"
column="48"/>
</issue>
@@ -6080,29 +5057,18 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2498"
+ line="2608"
column="48"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" boolean isScoOn = mSystemInterface.getAudioManager().isBluetoothScoOn();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2559"
- column="44"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" ProfileService.println(sb, "Telecom.isInCall(): " + mSystemInterface.isInCall());"
errorLine2=" ~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2585"
+ line="2695"
column="82"/>
</issue>
@@ -6113,7 +5079,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2586"
+ line="2696"
column="83"/>
</issue>
@@ -6124,7 +5090,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2589"
+ line="2699"
column="69"/>
</issue>
@@ -6135,7 +5101,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java"
- line="2598"
+ line="2708"
column="43"/>
</issue>
@@ -6395,28 +5361,6 @@
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" mSystemInterface.getAudioManager().setA2dpSuspended(true);"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1334"
- column="38"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" mSystemInterface.getAudioManager().setLeAudioSuspended(true);"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1336"
- column="42"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" && mSystemInterface.isHighDefCallInProgress()) {"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
<location
@@ -6439,28 +5383,6 @@
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" mSystemInterface.getAudioManager().setA2dpSuspended(false);"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1354"
- column="42"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" mSystemInterface.getAudioManager().setLeAudioSuspended(false);"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1356"
- column="46"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" if (!mNativeInterface.disconnectAudio(mDevice)) {"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
@@ -6483,28 +5405,6 @@
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" .getAudioManager()"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1556"
- column="22"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" mSystemInterface.getAudioManager().clearAudioServerStateCallback();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1567"
- column="30"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" if (!mNativeInterface.disconnectAudio(mDevice)) {"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
@@ -6527,17 +5427,6 @@
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" AudioManager am = mSystemInterface.getAudioManager();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java"
- line="1870"
- column="44"/>
- </issue>
-
- <issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
errorLine1=" mNativeInterface.atResponseCode(mDevice, HeadsetHalConstants.AT_RESPONSE_ERROR, 0);"
errorLine2=" ~~~~~~~~~~~~~~">
<location
@@ -6762,18 +5651,18 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java"
- line="483"
+ line="452"
column="31"/>
</issue>
<issue
id="VisibleForTests"
message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.sendMessage(HearingAidStateMachine.STACK_EVENT, stackEvent);"
- errorLine2=" ~~~~~~~~~~~">
+ errorLine1=" sm.sendMessage(HearingAidStateMachine.MESSAGE_STACK_EVENT, stackEvent);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java"
- line="655"
+ line="624"
column="51"/>
</issue>
@@ -6839,7 +5728,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="187"
+ line="188"
column="5"/>
</issue>
@@ -6850,7 +5739,7 @@
errorLine2=" ~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="520"
+ line="531"
column="29"/>
</issue>
@@ -6861,7 +5750,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="566"
+ line="577"
column="39"/>
</issue>
@@ -6872,7 +5761,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="566"
+ line="577"
column="81"/>
</issue>
@@ -6883,7 +5772,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="579"
+ line="590"
column="52"/>
</issue>
@@ -6894,7 +5783,7 @@
errorLine2=" ~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="656"
+ line="667"
column="29"/>
</issue>
@@ -6905,7 +5794,7 @@
errorLine2=" ~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="2644"
+ line="2690"
column="52"/>
</issue>
@@ -6916,7 +5805,7 @@
errorLine2=" ~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="3393"
+ line="3439"
column="52"/>
</issue>
@@ -6927,7 +5816,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="4382"
+ line="4439"
column="31"/>
</issue>
@@ -6938,7 +5827,7 @@
errorLine2=" ~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java"
- line="4521"
+ line="4578"
column="29"/>
</issue>
@@ -8027,22 +6916,11 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/vc/VolumeControlService.java"
- line="416"
+ line="377"
column="26"/>
</issue>
<issue
- id="VisibleForTests"
- message="This method should only be accessed from tests or within private scope"
- errorLine1=" sm.sendMessage(VolumeControlStateMachine.STACK_EVENT, stackEvent);"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/vc/VolumeControlService.java"
- line="1316"
- column="54"/>
- </issue>
-
- <issue
id="MissingVersion"
message="Should set `android:versionCode` to specify the application version"
errorLine1="<manifest xmlns:android="http://schemas.android.com/apk/res/android""
@@ -8181,7 +7059,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="6169"
+ line="6172"
column="17"/>
</issue>
@@ -8269,7 +7147,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java"
- line="418"
+ line="546"
column="5"/>
</issue>
@@ -8280,7 +7158,7 @@
errorLine2=" ^">
<location
file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java"
- line="773"
+ line="777"
column="9"/>
</issue>
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
index b94a760..5c8344b 100644
--- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
+++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkService.java
@@ -27,8 +27,6 @@
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothA2dpSink;
import android.content.AttributionSource;
-import android.content.Context;
-import android.media.AudioManager;
import android.os.Looper;
import android.sysprop.BluetoothProperties;
import android.util.Log;
@@ -51,62 +49,43 @@
public class A2dpSinkService extends ProfileService {
private static final String TAG = A2dpSinkService.class.getSimpleName();
+ private static A2dpSinkService sService;
+
// This is also used as a lock for shared data in {@link A2dpSinkService}
@GuardedBy("mDeviceStateMap")
private final Map<BluetoothDevice, A2dpSinkStateMachine> mDeviceStateMap =
new ConcurrentHashMap<>(1);
+ private final Object mActiveDeviceLock = new Object();
+ private final Object mStreamHandlerLock = new Object();
+
+ private final AdapterService mAdapterService;
+ private final DatabaseManager mDatabaseManager;
private final A2dpSinkNativeInterface mNativeInterface;
private final Looper mLooper;
+ private final int mMaxConnectedAudioDevices;
- private final Object mActiveDeviceLock = new Object();
+ @GuardedBy("mStreamHandlerLock")
+ private final A2dpSinkStreamHandler mA2dpSinkStreamHandler;
@GuardedBy("mActiveDeviceLock")
private BluetoothDevice mActiveDevice = null;
- private final Object mStreamHandlerLock = new Object();
-
- @GuardedBy("mStreamHandlerLock")
- private A2dpSinkStreamHandler mA2dpSinkStreamHandler;
-
- private static A2dpSinkService sService;
-
- private int mMaxConnectedAudioDevices;
-
- private AdapterService mAdapterService;
- private DatabaseManager mDatabaseManager;
-
- public A2dpSinkService(Context ctx) {
- super(ctx);
- mNativeInterface = requireNonNull(A2dpSinkNativeInterface.getInstance());
- mLooper = Looper.getMainLooper();
+ public A2dpSinkService(AdapterService adapterService) {
+ this(adapterService, A2dpSinkNativeInterface.getInstance(), Looper.getMainLooper());
}
@VisibleForTesting
- A2dpSinkService(Context ctx, A2dpSinkNativeInterface nativeInterface, Looper looper) {
- super(ctx);
+ A2dpSinkService(
+ AdapterService adapterService, A2dpSinkNativeInterface nativeInterface, Looper looper) {
+ super(requireNonNull(adapterService));
+ mAdapterService = adapterService;
+ mDatabaseManager = requireNonNull(mAdapterService.getDatabase());
mNativeInterface = requireNonNull(nativeInterface);
mLooper = looper;
- }
-
- public static boolean isEnabled() {
- return BluetoothProperties.isProfileA2dpSinkEnabled().orElse(false);
- }
-
- @Override
- public void start() {
- mAdapterService =
- requireNonNull(
- AdapterService.getAdapterService(),
- "AdapterService cannot be null when A2dpSinkService starts");
- mDatabaseManager =
- requireNonNull(
- AdapterService.getAdapterService().getDatabase(),
- "DatabaseManager cannot be null when A2dpSinkService starts");
mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices();
mNativeInterface.init(mMaxConnectedAudioDevices);
-
synchronized (mStreamHandlerLock) {
mA2dpSinkStreamHandler = new A2dpSinkStreamHandler(this, mNativeInterface);
}
@@ -114,6 +93,10 @@
setA2dpSinkService(this);
}
+ public static boolean isEnabled() {
+ return BluetoothProperties.isProfileA2dpSinkEnabled().orElse(false);
+ }
+
@Override
public void stop() {
setA2dpSinkService(null);
@@ -125,10 +108,7 @@
mDeviceStateMap.clear();
}
synchronized (mStreamHandlerLock) {
- if (mA2dpSinkStreamHandler != null) {
- mA2dpSinkStreamHandler.cleanup();
- mA2dpSinkStreamHandler = null;
- }
+ mA2dpSinkStreamHandler.cleanup();
}
}
@@ -164,7 +144,6 @@
/** Request audio focus such that the designated device can stream audio */
public void requestAudioFocus(BluetoothDevice device, boolean request) {
synchronized (mStreamHandlerLock) {
- if (mA2dpSinkStreamHandler == null) return;
mA2dpSinkStreamHandler.requestAudioFocus(request);
}
}
@@ -176,17 +155,12 @@
*/
public int getFocusState() {
synchronized (mStreamHandlerLock) {
- if (mA2dpSinkStreamHandler == null) return AudioManager.ERROR;
return mA2dpSinkStreamHandler.getFocusState();
}
}
- @RequiresPermission(BLUETOOTH_PRIVILEGED)
boolean isA2dpPlaying(BluetoothDevice device) {
- enforceCallingOrSelfPermission(
- BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission");
synchronized (mStreamHandlerLock) {
- if (mA2dpSinkStreamHandler == null) return false;
return mA2dpSinkStreamHandler.isPlaying();
}
}
@@ -309,6 +283,9 @@
if (service == null) {
return false;
}
+
+ service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null);
+
return service.isA2dpPlaying(device);
}
@@ -407,19 +384,14 @@
}
protected A2dpSinkStateMachine getOrCreateStateMachine(BluetoothDevice device) {
- A2dpSinkStateMachine newStateMachine =
- new A2dpSinkStateMachine(mLooper, device, this, mNativeInterface);
synchronized (mDeviceStateMap) {
- A2dpSinkStateMachine existingStateMachine =
- mDeviceStateMap.putIfAbsent(device, newStateMachine);
- // Given null is not a valid value in our map, ConcurrentHashMap will return null if the
- // key was absent and our new value was added. We should then start and return it. Else
- // we quit the new one so we don't leak a thread
- if (existingStateMachine == null) {
- newStateMachine.start();
- return newStateMachine;
+ A2dpSinkStateMachine sm = mDeviceStateMap.get(device);
+ if (sm != null) {
+ return sm;
}
- return existingStateMachine;
+ sm = new A2dpSinkStateMachine(this, device, mLooper, mNativeInterface);
+ mDeviceStateMap.put(device, sm);
+ return sm;
}
}
@@ -469,8 +441,8 @@
stateMachine = mDeviceStateMap.get(device);
}
return (stateMachine == null)
- ? BluetoothProfile.STATE_DISCONNECTED
- : stateMachine.getState();
+ ? BluetoothProfile.STATE_DISCONNECTED
+ : stateMachine.getState();
}
/**
@@ -543,18 +515,10 @@
/** Receive and route a stack event from the JNI */
protected void messageFromNative(StackEvent event) {
switch (event.mType) {
- case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
- onConnectionStateChanged(event);
- return;
- case StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED:
- onAudioStateChanged(event);
- return;
- case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED:
- onAudioConfigChanged(event);
- return;
- default:
- Log.e(TAG, "Received unknown stack event of type " + event.mType);
- return;
+ case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> onConnectionStateChanged(event);
+ case StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED -> onAudioStateChanged(event);
+ case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED -> onAudioConfigChanged(event);
+ default -> Log.e(TAG, "Received unknown stack event of type " + event.mType);
}
}
@@ -570,18 +534,11 @@
private void onAudioStateChanged(StackEvent event) {
int state = event.mState;
synchronized (mStreamHandlerLock) {
- if (mA2dpSinkStreamHandler == null) {
- Log.e(TAG, "Received audio state change before we've been started");
- return;
- } else if (state == StackEvent.AUDIO_STATE_STARTED) {
- mA2dpSinkStreamHandler
- .obtainMessage(A2dpSinkStreamHandler.SRC_STR_START)
- .sendToTarget();
+ if (state == StackEvent.AUDIO_STATE_STARTED) {
+ mA2dpSinkStreamHandler.sendEmptyMessage(A2dpSinkStreamHandler.SRC_STR_START);
} else if (state == StackEvent.AUDIO_STATE_STOPPED
|| state == StackEvent.AUDIO_STATE_REMOTE_SUSPEND) {
- mA2dpSinkStreamHandler
- .obtainMessage(A2dpSinkStreamHandler.SRC_STR_STOP)
- .sendToTarget();
+ mA2dpSinkStreamHandler.sendEmptyMessage(A2dpSinkStreamHandler.SRC_STR_STOP);
} else {
Log.w(TAG, "Unhandled audio state change, state=" + state);
}
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java
index 48cb1bb..18d956b 100644
--- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java
+++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java
@@ -17,6 +17,11 @@
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+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 android.annotation.RequiresPermission;
import android.bluetooth.BluetoothA2dpSink;
@@ -41,15 +46,15 @@
private static final String TAG = A2dpSinkStateMachine.class.getSimpleName();
// 0->99 Events from Outside
- @VisibleForTesting static final int CONNECT = 1;
- @VisibleForTesting static final int DISCONNECT = 2;
+ @VisibleForTesting static final int MESSAGE_CONNECT = 1;
+ @VisibleForTesting static final int MESSAGE_DISCONNECT = 2;
// 100->199 Internal Events
@VisibleForTesting static final int CLEANUP = 100;
- @VisibleForTesting static final int CONNECT_TIMEOUT = 101;
+ @VisibleForTesting static final int MESSAGE_CONNECT_TIMEOUT = 101;
// 200->299 Events from Native
- @VisibleForTesting static final int STACK_EVENT = 200;
+ @VisibleForTesting static final int MESSAGE_STACK_EVENT = 200;
static final int CONNECT_TIMEOUT_MS = 10000;
@@ -62,13 +67,13 @@
protected final Connected mConnected;
protected final Disconnecting mDisconnecting;
- protected int mMostRecentState = BluetoothProfile.STATE_DISCONNECTED;
+ protected int mMostRecentState = STATE_DISCONNECTED;
protected BluetoothAudioConfig mAudioConfig = null;
A2dpSinkStateMachine(
- Looper looper,
- BluetoothDevice device,
A2dpSinkService service,
+ BluetoothDevice device,
+ Looper looper,
A2dpSinkNativeInterface nativeInterface) {
super(TAG, looper);
mDevice = device;
@@ -88,6 +93,7 @@
setInitialState(mDisconnected);
Log.d(TAG, "[" + mDevice + "] State machine created");
+ start();
}
/**
@@ -115,17 +121,17 @@
/** send the Connect command asynchronously */
final void connect() {
- sendMessage(CONNECT);
+ sendMessage(MESSAGE_CONNECT);
}
/** send the Disconnect command asynchronously */
final void disconnect() {
- sendMessage(DISCONNECT);
+ sendMessage(MESSAGE_DISCONNECT);
}
/** send the stack event asynchronously */
final void onStackEvent(StackEvent event) {
- sendMessage(STACK_EVENT, event);
+ sendMessage(MESSAGE_STACK_EVENT, event);
}
/**
@@ -154,56 +160,50 @@
@Override
public void enter() {
Log.d(TAG, "[" + mDevice + "] Enter Disconnected");
- if (mMostRecentState != BluetoothProfile.STATE_DISCONNECTED) {
+ if (mMostRecentState != STATE_DISCONNECTED) {
sendMessage(CLEANUP);
}
- onConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTED);
+ onConnectionStateChanged(STATE_DISCONNECTED);
}
@Override
public boolean processMessage(Message message) {
switch (message.what) {
- case STACK_EVENT:
- processStackEvent((StackEvent) message.obj);
- return true;
- case CONNECT:
+ case MESSAGE_STACK_EVENT -> processStackEvent((StackEvent) message.obj);
+ case MESSAGE_CONNECT -> {
Log.d(TAG, "[" + mDevice + "] Connect");
transitionTo(mConnecting);
- return true;
- case CLEANUP:
- mService.removeStateMachine(A2dpSinkStateMachine.this);
- return true;
+ }
+ case CLEANUP -> mService.removeStateMachine(A2dpSinkStateMachine.this);
+ default -> {
+ return false;
+ }
}
- return false;
+ return true;
}
@RequiresPermission(BLUETOOTH_PRIVILEGED)
void processStackEvent(StackEvent event) {
- switch (event.mType) {
- case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
- switch (event.mState) {
- case StackEvent.CONNECTION_STATE_CONNECTING:
- if (mService.getConnectionPolicy(mDevice)
- == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
- Log.w(
- TAG,
- "["
- + mDevice
- + "] Ignore incoming connection, profile"
- + " is turned off");
- mNativeInterface.disconnectA2dpSink(mDevice);
- } else {
- mConnecting.mIncomingConnection = true;
- transitionTo(mConnecting);
- }
- break;
- case StackEvent.CONNECTION_STATE_CONNECTED:
- transitionTo(mConnected);
- break;
- case StackEvent.CONNECTION_STATE_DISCONNECTED:
- sendMessage(CLEANUP);
- break;
+ if (event.mType != StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
+ return;
+ }
+ switch (event.mState) {
+ case STATE_CONNECTING -> {
+ if (mService.getConnectionPolicy(mDevice) == CONNECTION_POLICY_FORBIDDEN) {
+ Log.w(
+ TAG,
+ "["
+ + mDevice
+ + "] Ignore incoming connection, profile"
+ + " is turned off");
+ mNativeInterface.disconnectA2dpSink(mDevice);
+ } else {
+ mConnecting.mIncomingConnection = true;
+ transitionTo(mConnecting);
}
+ }
+ case STATE_CONNECTED -> transitionTo(mConnected);
+ case STATE_DISCONNECTED -> sendMessage(CLEANUP);
}
}
}
@@ -214,8 +214,8 @@
@Override
public void enter() {
Log.d(TAG, "[" + mDevice + "] Enter Connecting");
- onConnectionStateChanged(BluetoothProfile.STATE_CONNECTING);
- sendMessageDelayed(CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS);
+ onConnectionStateChanged(STATE_CONNECTING);
+ sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT_MS);
if (!mIncomingConnection) {
mNativeInterface.connectA2dpSink(mDevice);
@@ -227,13 +227,9 @@
@Override
public boolean processMessage(Message message) {
switch (message.what) {
- case STACK_EVENT:
- processStackEvent((StackEvent) message.obj);
- return true;
- case CONNECT_TIMEOUT:
- transitionTo(mDisconnected);
- return true;
- case DISCONNECT:
+ case MESSAGE_STACK_EVENT -> processStackEvent((StackEvent) message.obj);
+ case MESSAGE_CONNECT_TIMEOUT -> transitionTo(mDisconnected);
+ case MESSAGE_DISCONNECT -> {
Log.d(
TAG,
"["
@@ -241,28 +237,27 @@
+ "] Received disconnect message while connecting."
+ "deferred");
deferMessage(message);
- return true;
+ }
+ default -> {
+ return false;
+ }
}
- return false;
+ return true;
}
void processStackEvent(StackEvent event) {
- switch (event.mType) {
- case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
- switch (event.mState) {
- case StackEvent.CONNECTION_STATE_CONNECTED:
- transitionTo(mConnected);
- break;
- case StackEvent.CONNECTION_STATE_DISCONNECTED:
- transitionTo(mDisconnected);
- break;
- }
+ if (event.mType != StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
+ return;
+ }
+ switch (event.mState) {
+ case STATE_CONNECTED -> transitionTo(mConnected);
+ case STATE_DISCONNECTED -> transitionTo(mDisconnected);
}
}
@Override
public void exit() {
- removeMessages(CONNECT_TIMEOUT);
+ removeMessages(MESSAGE_CONNECT_TIMEOUT);
mIncomingConnection = false;
}
}
@@ -271,42 +266,39 @@
@Override
public void enter() {
Log.d(TAG, "[" + mDevice + "] Enter Connected");
- onConnectionStateChanged(BluetoothProfile.STATE_CONNECTED);
+ onConnectionStateChanged(STATE_CONNECTED);
}
@Override
public boolean processMessage(Message message) {
switch (message.what) {
- case DISCONNECT:
+ case MESSAGE_DISCONNECT -> {
transitionTo(mDisconnecting);
mNativeInterface.disconnectA2dpSink(mDevice);
- return true;
- case STACK_EVENT:
- processStackEvent((StackEvent) message.obj);
- return true;
+ }
+ case MESSAGE_STACK_EVENT -> processStackEvent((StackEvent) message.obj);
+ default -> {
+ return false;
+ }
}
- return false;
+ return true;
}
void processStackEvent(StackEvent event) {
switch (event.mType) {
- case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
+ case StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> {
switch (event.mState) {
- case StackEvent.CONNECTION_STATE_DISCONNECTING:
- transitionTo(mDisconnecting);
- break;
- case StackEvent.CONNECTION_STATE_DISCONNECTED:
- transitionTo(mDisconnected);
- break;
+ case STATE_DISCONNECTING -> transitionTo(mDisconnecting);
+ case STATE_DISCONNECTED -> transitionTo(mDisconnected);
}
- break;
- case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED:
+ }
+ case StackEvent.EVENT_TYPE_AUDIO_CONFIG_CHANGED -> {
mAudioConfig =
new BluetoothAudioConfig(
event.mSampleRate,
event.mChannelCount,
AudioFormat.ENCODING_PCM_16BIT);
- break;
+ }
}
}
}
@@ -315,7 +307,7 @@
@Override
public void enter() {
Log.d(TAG, "[" + mDevice + "] Enter Disconnecting");
- onConnectionStateChanged(BluetoothProfile.STATE_DISCONNECTING);
+ onConnectionStateChanged(STATE_DISCONNECTING);
transitionTo(mDisconnected);
}
}
@@ -324,7 +316,7 @@
if (mMostRecentState == currentState) {
return;
}
- if (currentState == BluetoothProfile.STATE_CONNECTED) {
+ if (currentState == STATE_CONNECTED) {
MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.A2DP_SINK);
}
Log.d(TAG, "[" + mDevice + "] Connection state: " + mMostRecentState + "->" + currentState);
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
index 6cf7d99..e62f924 100644
--- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
+++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandler.java
@@ -70,9 +70,10 @@
private static final int STATE_FOCUS_GRANTED = 1;
// Private variables.
- private A2dpSinkService mA2dpSinkService;
- private A2dpSinkNativeInterface mNativeInterface;
- private AudioManager mAudioManager;
+ private final A2dpSinkService mA2dpSinkService;
+ private final A2dpSinkNativeInterface mNativeInterface;
+ private final AudioManager mAudioManager;
+
// Keep track if the remote device is providing audio
private boolean mStreamAvailable = false;
// Keep track of the relevant audio focus (None, Transient, Gain)
diff --git a/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java b/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java
index 1a1429a..0c88599 100644
--- a/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java
+++ b/android/app/src/com/android/bluetooth/a2dpsink/StackEvent.java
@@ -24,12 +24,6 @@
static final int EVENT_TYPE_AUDIO_STATE_CHANGED = 2;
static final int EVENT_TYPE_AUDIO_CONFIG_CHANGED = 3;
- // match up with btav_connection_state_t enum of bt_av.h
- static final int CONNECTION_STATE_DISCONNECTED = 0;
- static final int CONNECTION_STATE_CONNECTING = 1;
- static final int CONNECTION_STATE_CONNECTED = 2;
- static final int CONNECTION_STATE_DISCONNECTING = 3;
-
// match up with btav_audio_state_t enum of bt_av.h
static final int AUDIO_STATE_REMOTE_SUSPEND = 0;
static final int AUDIO_STATE_STOPPED = 1;
diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
index 17bf92f..93579a8 100644
--- a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
+++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
@@ -16,6 +16,8 @@
package com.android.bluetooth.avrcp;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
@@ -62,14 +64,18 @@
private final BluetoothEventLogger mMediaKeyEventLogger =
new BluetoothEventLogger(MEDIA_KEY_EVENT_LOGGER_SIZE, MEDIA_KEY_EVENT_LOGGER_TITLE);
- private AvrcpVersion mAvrcpVersion;
- private MediaPlayerList mMediaPlayerList;
- private PlayerSettingsManager mPlayerSettingsManager;
- private AudioManager mAudioManager;
- private AvrcpBroadcastReceiver mReceiver;
- private AvrcpNativeInterface mNativeInterface;
- private AvrcpVolumeManager mVolumeManager;
- private ServiceFactory mFactory = new ServiceFactory();
+ // Cover Art Service (Storage + BIP Server)
+ private final AvrcpCoverArtService mAvrcpCoverArtService;
+ private final AdapterService mAdapterService;
+ private final AvrcpVersion mAvrcpVersion;
+ private final MediaPlayerList mMediaPlayerList;
+ private final PlayerSettingsManager mPlayerSettingsManager;
+ private final AudioManager mAudioManager;
+ private final AvrcpBroadcastReceiver mReceiver;
+ private final AvrcpNativeInterface mNativeInterface;
+ private final AvrcpVolumeManager mVolumeManager;
+
+ private final ServiceFactory mFactory = new ServiceFactory();
private final BroadcastReceiver mUserUnlockedReceiver =
new BroadcastReceiver() {
@Override
@@ -84,24 +90,65 @@
Log.e(TAG, "userChangeReceiver received an invalid EXTRA_USER_HANDLE");
return;
}
- if (mMediaPlayerList != null) {
- mMediaPlayerList.init(new ListCallback());
- }
+ mMediaPlayerList.init(new ListCallback());
}
};
// Only used to see if the metadata has changed from its previous value
private MediaData mCurrentData;
- // Cover Art Service (Storage + BIP Server)
- private AvrcpCoverArtService mAvrcpCoverArtService = null;
-
private static AvrcpTargetService sInstance = null;
- private final AdapterService mAdapterService;
public AvrcpTargetService(AdapterService adapterService) {
- super(adapterService);
+ super(requireNonNull(adapterService));
mAdapterService = adapterService;
+ mAudioManager = requireNonNull(getSystemService(AudioManager.class));
+ mNativeInterface = requireNonNull(AvrcpNativeInterface.getInstance());
+
+ mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this);
+
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
+ getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter);
+
+ Log.i(TAG, "Starting the AVRCP Target Service");
+ mCurrentData = new MediaData(null, null, null);
+
+ mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this);
+ mNativeInterface.init(this);
+
+ mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue();
+ mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface);
+
+ UserManager userManager = getApplicationContext().getSystemService(UserManager.class);
+ if (userManager.isUserUnlocked()) {
+ mMediaPlayerList.init(new ListCallback());
+ }
+
+ if (!getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) {
+ mAvrcpCoverArtService = null;
+ } else if (!mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) {
+ Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art");
+ mAvrcpCoverArtService = null;
+ } else {
+ AvrcpCoverArtService coverArtService = new AvrcpCoverArtService();
+ if (coverArtService.start()) {
+ mAvrcpCoverArtService = coverArtService;
+ } else {
+ Log.e(TAG, "Failed to start cover art service");
+ mAvrcpCoverArtService = null;
+ }
+ }
+
+ mReceiver = new AvrcpBroadcastReceiver();
+ IntentFilter filter = new IntentFilter();
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ filter.addAction(AudioManager.ACTION_VOLUME_CHANGED);
+ registerReceiver(mReceiver, filter);
+
+ // Only allow the service to be used once it is initialized
+ sInstance = this;
}
/** Checks for profile enabled state in Bluetooth sysprops. */
@@ -113,8 +160,6 @@
class ListCallback implements MediaPlayerList.MediaUpdateCallback {
@Override
public void run(MediaData data) {
- if (mNativeInterface == null) return;
-
boolean metadata = !Objects.equals(mCurrentData.metadata, data.metadata);
boolean state = !MediaPlayerWrapper.playstateEquals(mCurrentData.state, data.state);
boolean queue = isQueueUpdated(mCurrentData.queue, data.queue);
@@ -134,8 +179,6 @@
@Override
public void run(boolean availablePlayers, boolean addressedPlayers, boolean uids) {
- if (mNativeInterface == null) return;
-
mNativeInterface.sendFolderUpdate(availablePlayers, addressedPlayers, uids);
}
}
@@ -148,17 +191,18 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(AudioManager.ACTION_VOLUME_CHANGED)) {
- int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
- if (streamType == AudioManager.STREAM_MUSIC) {
- int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
- BluetoothDevice activeDevice = getA2dpActiveDevice();
- if (activeDevice != null
- && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) {
- Log.d(TAG, "stream volume change to " + volume + " " + activeDevice);
- mVolumeManager.storeVolumeForDevice(activeDevice, volume);
- }
- }
+ if (!action.equals(AudioManager.ACTION_VOLUME_CHANGED)) {
+ return;
+ }
+ int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ if (streamType != AudioManager.STREAM_MUSIC) {
+ return;
+ }
+ int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
+ BluetoothDevice activeDevice = getA2dpActiveDevice();
+ if (activeDevice != null && !mVolumeManager.getAbsoluteVolumeSupported(activeDevice)) {
+ Log.d(TAG, "stream volume change to " + volume + " " + activeDevice);
+ mVolumeManager.storeVolumeForDevice(activeDevice, volume);
}
}
}
@@ -194,61 +238,6 @@
}
@Override
- public void start() {
- if (sInstance != null) {
- throw new IllegalStateException("start() called twice");
- }
-
- IntentFilter userFilter = new IntentFilter();
- userFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- userFilter.addAction(Intent.ACTION_USER_UNLOCKED);
- getApplicationContext().registerReceiver(mUserUnlockedReceiver, userFilter);
-
- Log.i(TAG, "Starting the AVRCP Target Service");
- mCurrentData = new MediaData(null, null, null);
-
- mAudioManager = getSystemService(AudioManager.class);
-
- mMediaPlayerList = new MediaPlayerList(Looper.myLooper(), this);
-
- mPlayerSettingsManager = new PlayerSettingsManager(mMediaPlayerList, this);
-
- mNativeInterface = AvrcpNativeInterface.getInstance();
- mNativeInterface.init(AvrcpTargetService.this);
-
- mAvrcpVersion = AvrcpVersion.getCurrentSystemPropertiesValue();
-
- mVolumeManager = new AvrcpVolumeManager(mAdapterService, mAudioManager, mNativeInterface);
-
- UserManager userManager = getApplicationContext().getSystemService(UserManager.class);
- if (userManager.isUserUnlocked()) {
- mMediaPlayerList.init(new ListCallback());
- }
-
- if (getResources().getBoolean(R.bool.avrcp_target_enable_cover_art)) {
- if (mAvrcpVersion.isAtleastVersion(AvrcpVersion.AVRCP_VERSION_1_6)) {
- mAvrcpCoverArtService = new AvrcpCoverArtService();
- boolean started = mAvrcpCoverArtService.start();
- if (!started) {
- Log.e(TAG, "Failed to start cover art service");
- mAvrcpCoverArtService = null;
- }
- } else {
- Log.e(TAG, "Please use AVRCP version 1.6 to enable cover art");
- }
- }
-
- mReceiver = new AvrcpBroadcastReceiver();
- IntentFilter filter = new IntentFilter();
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- filter.addAction(AudioManager.ACTION_VOLUME_CHANGED);
- registerReceiver(mReceiver, filter);
-
- // Only allow the service to be used once it is initialized
- sInstance = this;
- }
-
- @Override
public void stop() {
Log.i(TAG, "Stopping the AVRCP Target Service");
@@ -260,22 +249,15 @@
if (mAvrcpCoverArtService != null) {
mAvrcpCoverArtService.stop();
}
- mAvrcpCoverArtService = null;
sInstance = null;
unregisterReceiver(mReceiver);
// We check the interfaces first since they only get set on User Unlocked
- if (mPlayerSettingsManager != null) mPlayerSettingsManager.cleanup();
- if (mMediaPlayerList != null) mMediaPlayerList.cleanup();
- if (mNativeInterface != null) mNativeInterface.cleanup();
+ mPlayerSettingsManager.cleanup();
+ mMediaPlayerList.cleanup();
+ mNativeInterface.cleanup();
getApplicationContext().unregisterReceiver(mUserUnlockedReceiver);
-
- mPlayerSettingsManager = null;
- mMediaPlayerList = null;
- mNativeInterface = null;
- mAudioManager = null;
- mReceiver = null;
}
/** Returns the active A2DP {@link BluetoothDevice} */
@@ -339,7 +321,7 @@
* <p>If the A2DP connection disconnects, we request AVRCP to disconnect device as well.
*/
public void handleA2dpConnectionStateChanged(BluetoothDevice device, int newState) {
- if (device == null || mNativeInterface == null) return;
+ if (device == null) return;
if (newState == BluetoothProfile.STATE_DISCONNECTED) {
// If there is no connection, disconnectDevice() will do nothing
if (mNativeInterface.disconnectDevice(device)) {
@@ -359,10 +341,8 @@
*/
public void handleA2dpActiveDeviceChanged(BluetoothDevice device) {
mVolumeManager.volumeDeviceSwitched(device);
- if (mNativeInterface != null) {
- // Update all the playback status info for each connected device
- mNativeInterface.sendMediaUpdate(false, true, false);
- }
+ // Update all the playback status info for each connected device
+ mNativeInterface.sendMediaUpdate(false, true, false);
}
/** Informs {@link AvrcpVolumeManager} that a remote device requests a volume change */
@@ -575,11 +555,6 @@
/** Called from player callback to indicate new settings to remote device. */
public void sendPlayerSettings(int repeatMode, int shuffleMode) {
- if (mNativeInterface == null) {
- Log.i(TAG, "Tried to send Player Settings while native interface is null");
- return;
- }
-
mNativeInterface.sendPlayerSettings(repeatMode, shuffleMode);
}
@@ -626,11 +601,7 @@
StringBuilder tempBuilder = new StringBuilder();
tempBuilder.append("AVRCP version: ").append(mAvrcpVersion).append("\n");
- if (mMediaPlayerList != null) {
- mMediaPlayerList.dump(tempBuilder);
- } else {
- tempBuilder.append("\nMedia Player List is empty\n");
- }
+ mMediaPlayerList.dump(tempBuilder);
mMediaKeyEventLogger.dump(tempBuilder);
tempBuilder.append("\n");
diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java b/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java
index a8c31ea..298162a 100644
--- a/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java
+++ b/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java
@@ -77,15 +77,6 @@
.setBrowsable(true)
.build());
mRootNode.setCached(true);
- } else if (!Flags.randomizeDeviceLevelMediaIds()) {
- mRootNode =
- new BrowseNode(
- new AvrcpItem.Builder()
- .setDevice(device)
- .setUuid(ROOT + device.getAddress().toString())
- .setTitle(Utils.getName(device))
- .setBrowsable(true)
- .build());
} else {
mRootNode =
new BrowseNode(
@@ -184,11 +175,7 @@
BrowseNode(BluetoothDevice device) {
AvrcpItem.Builder aid = new AvrcpItem.Builder();
aid.setDevice(device);
- if (Flags.randomizeDeviceLevelMediaIds()) {
- aid.setUuid(ROOT + device.getAddress().toString() + UUID.randomUUID().toString());
- } else {
- aid.setUuid(PLAYER_PREFIX + device.getAddress().toString());
- }
+ aid.setUuid(ROOT + device.getAddress().toString() + UUID.randomUUID().toString());
aid.setDisplayableName(Utils.getName(device));
aid.setTitle(Utils.getName(device));
aid.setBrowsable(true);
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 7a0389a..957b02c 100644
--- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
+++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java
@@ -23,6 +23,7 @@
import static com.android.bluetooth.flags.Flags.leaudioAllowedContextMask;
import static com.android.bluetooth.flags.Flags.leaudioBigDependsOnAudioState;
+import static com.android.bluetooth.flags.Flags.leaudioBroadcastApiGetLocalMetadata;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastAssistantPeripheralEntrustment;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastExtractPeriodicScannerFromStateMachine;
import static com.android.bluetooth.flags.Flags.leaudioBroadcastResyncHelper;
@@ -3273,6 +3274,27 @@
return stateMachine.getMaximumSourceCapacity();
}
+ /**
+ * Get metadata of source that stored on this Broadcast Sink
+ *
+ * @param sink Broadcast Sink device
+ * @param sourceId Broadcast source id
+ * @return metadata of source that stored on this Broadcast Sink
+ */
+ BluetoothLeBroadcastMetadata getSourceMetadata(BluetoothDevice sink, int sourceId) {
+ if (!leaudioBroadcastApiGetLocalMetadata()) {
+ return null;
+ }
+
+ log("getSourceMetadata: device = " + sink + " with source id = " + sourceId);
+ BassClientStateMachine stateMachine = getOrCreateStateMachine(sink);
+ if (stateMachine == null) {
+ log("stateMachine is null");
+ return null;
+ }
+ return stateMachine.getCurrentBroadcastMetadata(sourceId);
+ }
+
private boolean isLocalBroadcast(int broadcastId) {
LeAudioService leAudioService = mServiceFactory.getLeAudioService();
if (leAudioService == null) {
@@ -4630,5 +4652,16 @@
}
return service.getMaximumSourceCapacity(sink);
}
+
+ @Override
+ public BluetoothLeBroadcastMetadata getSourceMetadata(
+ BluetoothDevice sink, int sourceId, AttributionSource source) {
+ BassClientService service = getServiceAndEnforceConnect(source);
+ if (service == null) {
+ Log.e(TAG, "Service is null");
+ return null;
+ }
+ return service.getSourceMetadata(sink, sourceId);
+ }
}
}
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 b59ff2f..021b732 100644
--- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java
+++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java
@@ -376,10 +376,6 @@
return mPendingSourceToSwitch != null;
}
- BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) {
- return mCurrentMetadata.getOrDefault(sourceId, null);
- }
-
private void setCurrentBroadcastMetadata(
Integer sourceId, BluetoothLeBroadcastMetadata metadata) {
if (metadata != null) {
@@ -2619,6 +2615,10 @@
return mNumOfBroadcastReceiverStates;
}
+ BluetoothLeBroadcastMetadata getCurrentBroadcastMetadata(Integer sourceId) {
+ return mCurrentMetadata.getOrDefault(sourceId, null);
+ }
+
BluetoothDevice getDevice() {
return mDevice;
}
diff --git a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java
index 8520bc3..4b563ac 100644
--- a/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java
+++ b/android/app/src/com/android/bluetooth/btservice/ActiveDeviceManager.java
@@ -688,6 +688,14 @@
if (device != null) {
// remove LE audio active device when it is not null, and not dual mode
setLeAudioActiveDevice(null, true);
+ } else {
+ Log.d(
+ TAG,
+ "HFP active device is null. Try to fallback to le audio active"
+ + " device");
+ synchronized (mLock) {
+ setFallbackDeviceActiveLocked(device);
+ }
}
}
}
@@ -782,6 +790,13 @@
mLeHearingAidActiveDevice = device;
}
+ if (device == null && !Utils.isDualModeAudioEnabled()) {
+ Log.d(TAG, "LE audio active device is null. Try to fallback to hfp active device.");
+ synchronized (mLock) {
+ setFallbackDeviceActiveLocked(device);
+ }
+ }
+
mLeAudioActiveDevice = device;
}
}
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
index 43752e6..851df2c 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -30,6 +30,7 @@
import android.bluetooth.BluetoothMap;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothSap;
+import android.bluetooth.BluetoothUtils;
import android.bluetooth.BufferConstraint;
import android.bluetooth.BufferConstraints;
import android.content.Context;
@@ -651,7 +652,8 @@
BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
prevAdapterState)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- logProfileConnectionStateChange(device, newState, prevState);
+ MetricsLogger.getInstance()
+ .logProfileConnectionStateChange(device, profile, newState, prevState);
Log.d(TAG, "updateOnProfileConnectionChanged: " + logInfo);
mService.sendBroadcastAsUser(
intent,
@@ -662,33 +664,7 @@
}
}
- private void logProfileConnectionStateChange(BluetoothDevice device, int state, int prevState) {
- switch (state) {
- case BluetoothAdapter.STATE_CONNECTED:
- MetricsLogger.getInstance()
- .logBluetoothEvent(
- device,
- BluetoothStatsLog
- .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION,
- BluetoothStatsLog
- .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS,
- 0);
- break;
- case BluetoothAdapter.STATE_DISCONNECTED:
- if (prevState == BluetoothAdapter.STATE_CONNECTING) {
- MetricsLogger.getInstance()
- .logBluetoothEvent(
- device,
- BluetoothStatsLog
- .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION,
- BluetoothStatsLog
- .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL,
- 0);
- }
- break;
- }
- }
private boolean validateProfileConnectionState(int state) {
return (state == BluetoothProfile.STATE_DISCONNECTED
@@ -1102,7 +1078,7 @@
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
writer.println(TAG);
writer.println(" " + "Name: " + getName());
- writer.println(" " + "Address: " + Utils.getAddressStringFromByte(mAddress));
+ writer.println(" " + "Address: " + Utils.getRedactedAddressStringFromByte(mAddress));
writer.println(" " + "ConnectionState: " + dumpConnectionState(getConnectionState()));
writer.println(" " + "State: " + BluetoothAdapter.nameForState(getState()));
writer.println(" " + "MaxConnectedAudioDevices: " + getMaxConnectedAudioDevices());
@@ -1121,7 +1097,7 @@
if (brEdrAddress.equals(address)) {
writer.println(
" "
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ " ["
+ dumpDeviceType(mRemoteDevices.getType(device))
+ "][ 0x"
@@ -1130,9 +1106,9 @@
+ Utils.getName(device));
} else {
sb.append(" ")
- .append(address)
+ .append(BluetoothUtils.toAnonymizedAddress(address))
.append(" => ")
- .append(brEdrAddress)
+ .append(BluetoothUtils.toAnonymizedAddress(brEdrAddress))
.append(" [")
.append(dumpDeviceType(mRemoteDevices.getType(device)))
.append("][ 0x")
diff --git a/android/app/src/com/android/bluetooth/btservice/InteropUtil.java b/android/app/src/com/android/bluetooth/btservice/InteropUtil.java
index 93ab3ac4..da6eb5b 100644
--- a/android/app/src/com/android/bluetooth/btservice/InteropUtil.java
+++ b/android/app/src/com/android/bluetooth/btservice/InteropUtil.java
@@ -17,6 +17,7 @@
package com.android.bluetooth.btservice;
+import android.bluetooth.BluetoothUtils;
import android.util.Log;
/**
@@ -62,7 +63,12 @@
return false;
}
- Log.d(TAG, "interopMatchAddr: feature=" + feature.name() + ", address=" + address);
+ Log.d(
+ TAG,
+ "interopMatchAddr: feature="
+ + feature.name()
+ + ", address="
+ + BluetoothUtils.toAnonymizedAddress(address));
if (address == null) {
return false;
}
@@ -121,7 +127,12 @@
return false;
}
- Log.d(TAG, "interopMatchAddrOrName: feature=" + feature.name() + ", address=" + address);
+ Log.d(
+ TAG,
+ "interopMatchAddrOrName: feature="
+ + feature.name()
+ + ", address="
+ + BluetoothUtils.toAnonymizedAddress(address));
if (address == null) {
return false;
}
@@ -156,7 +167,7 @@
"interopDatabaseAddAddr: feature="
+ feature.name()
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", length="
+ length);
if (address == null || (length <= 0 || length > 6)) {
@@ -184,7 +195,12 @@
return;
}
- Log.d(TAG, "interopDatabaseRemoveAddr: feature=" + feature.name() + ", address=" + address);
+ Log.d(
+ TAG,
+ "interopDatabaseRemoveAddr: feature="
+ + feature.name()
+ + ", address="
+ + BluetoothUtils.toAnonymizedAddress(address));
if (address == null) {
return;
}
diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
index 6031e3b..9804048 100644
--- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
+++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java
@@ -15,11 +15,28 @@
*/
package com.android.bluetooth.btservice;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP_SINK;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_BATTERY;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_CSIP_SET_COORDINATOR;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HAP_CLIENT;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET_CLIENT;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEARING_AID;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HID_HOST;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO_BROADCAST_ASSISTANT;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_MAP_CLIENT;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PAN;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PBAP_CLIENT;
+import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_VOLUME_CONTROL;
import static com.android.bluetooth.BtRestrictedStatsLog.RESTRICTED_BLUETOOTH_DEVICE_NAME_REPORTED;
import android.app.AlarmManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothA2dpSink;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAvrcpController;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
@@ -714,6 +731,65 @@
return digest.digest(name.getBytes(StandardCharsets.UTF_8));
}
+ private int getProfileEnumFromProfileId(int profile) {
+ return switch (profile) {
+ case BluetoothProfile.A2DP ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP;
+ case BluetoothProfile.A2DP_SINK ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_A2DP_SINK;
+ case BluetoothProfile.HEADSET ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET;
+ case BluetoothProfile.HEADSET_CLIENT ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEADSET_CLIENT;
+ case BluetoothProfile.MAP_CLIENT ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_MAP_CLIENT;
+ case BluetoothProfile.HID_HOST ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HID_HOST;
+ case BluetoothProfile.PAN ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PAN;
+ case BluetoothProfile.PBAP_CLIENT ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_PBAP_CLIENT;
+ case BluetoothProfile.HEARING_AID ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HEARING_AID;
+ case BluetoothProfile.HAP_CLIENT ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_HAP_CLIENT;
+ case BluetoothProfile.VOLUME_CONTROL ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_VOLUME_CONTROL;
+ case BluetoothProfile.CSIP_SET_COORDINATOR ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_CSIP_SET_COORDINATOR;
+ case BluetoothProfile.LE_AUDIO ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO;
+ case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_LE_AUDIO_BROADCAST_ASSISTANT;
+ case BluetoothProfile.BATTERY ->
+ BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION_BATTERY;
+ default -> BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__PROFILE_CONNECTION;
+ };
+ }
+
+ public void logProfileConnectionStateChange(
+ BluetoothDevice device, int profileId, int state, int prevState) {
+
+ switch (state) {
+ case BluetoothAdapter.STATE_CONNECTED:
+ logBluetoothEvent(
+ device,
+ getProfileEnumFromProfileId(profileId),
+ BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS,
+ 0);
+ break;
+ case BluetoothAdapter.STATE_DISCONNECTED:
+ if (prevState == BluetoothAdapter.STATE_CONNECTING) {
+ logBluetoothEvent(
+ device,
+ getProfileEnumFromProfileId(profileId),
+ BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL,
+ 0);
+ }
+ break;
+ }
+ }
+
/** Logs LE Audio Broadcast audio session. */
public void logLeAudioBroadcastAudioSession(
int broadcastId,
diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
index bd64fb6..aa8395e 100644
--- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -31,6 +31,7 @@
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.BluetoothSinkAudioPolicy;
+import android.bluetooth.BluetoothUtils;
import android.bluetooth.IBluetoothConnectionCallback;
import android.content.Context;
import android.content.Intent;
@@ -183,7 +184,7 @@
debugLog(
"reset(): address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", connected="
+ bluetoothDevice.isConnected());
@@ -1168,7 +1169,7 @@
+ Utils.getRedactedAddressStringFromByte(secondaryAddress));
DeviceProperties deviceProperties = getDeviceProperties(device);
- deviceProperties.mIdentityAddress = Utils.getAddressStringFromByte(secondaryAddress);
+ deviceProperties.setIdentityAddress(Utils.getAddressStringFromByte(secondaryAddress));
}
void aclStateChangeCallback(
diff --git a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
index 9febc11..f1cdefc 100644
--- a/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
+++ b/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java
@@ -911,6 +911,16 @@
/** Process a change in the bonding state for a device */
public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) {
+ if (mHandler == null) {
+ Log.e(
+ TAG,
+ "mHandler is null, service is stopped. Ignore Bond State for "
+ + device
+ + " to state: "
+ + toState);
+ return;
+ }
+
mHandler.post(() -> bondStateChanged(device, toState));
}
@@ -972,6 +982,15 @@
}
void handleConnectionStateChanged(BluetoothDevice device, int fromState, int toState) {
+ if (mHandler == null) {
+ Log.e(
+ TAG,
+ "mHandler is null, service is stopped. Ignore Connection State for "
+ + device
+ + " to state: "
+ + toState);
+ return;
+ }
mHandler.post(() -> connectionStateChanged(device, fromState, toState));
}
diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java
index cf50002..036fded 100644
--- a/android/app/src/com/android/bluetooth/gatt/GattService.java
+++ b/android/app/src/com/android/bluetooth/gatt/GattService.java
@@ -1312,14 +1312,17 @@
+ ", connId="
+ connId
+ ", address="
- + address);
+ + BluetoothUtils.toAnonymizedAddress(address));
int connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
if (status == 0) {
mClientMap.addConnection(clientIf, connId, address);
// Allow one writeCharacteristic operation at a time for each connected remote device.
synchronized (mPermits) {
- Log.d(TAG, "onConnected() - adding permit for address=" + address);
+ Log.d(
+ TAG,
+ "onConnected() - adding permit for address="
+ + BluetoothUtils.toAnonymizedAddress(address));
mPermits.putIfAbsent(address, -1);
}
connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
@@ -1342,7 +1345,7 @@
+ ", connId="
+ connId
+ ", address="
- + address);
+ + BluetoothUtils.toAnonymizedAddress(address));
mClientMap.removeConnection(clientIf, connId);
ContextMap<IBluetoothGattCallback>.App app = mClientMap.getById(clientIf);
@@ -1355,13 +1358,19 @@
// device.
if (!mClientMap.getConnectedDevices().contains(address)) {
synchronized (mPermits) {
- Log.d(TAG, "onDisconnected() - removing permit for address=" + address);
+ Log.d(
+ TAG,
+ "onDisconnected() - removing permit for address="
+ + BluetoothUtils.toAnonymizedAddress(address));
mPermits.remove(address);
}
} else {
synchronized (mPermits) {
if (mPermits.get(address) == connId) {
- Log.d(TAG, "onDisconnected() - set permit -1 for address=" + address);
+ Log.d(
+ TAG,
+ "onDisconnected() - set permit -1 for address="
+ + BluetoothUtils.toAnonymizedAddress(address));
mPermits.put(address, -1);
}
}
@@ -1399,7 +1408,7 @@
Log.d(
TAG,
"onClientPhyRead() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", status="
+ status
+ ", clientIf="
@@ -1407,7 +1416,10 @@
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.d(TAG, "onClientPhyRead() - no connection to " + address);
+ Log.d(
+ TAG,
+ "onClientPhyRead() - no connection to "
+ + BluetoothUtils.toAnonymizedAddress(address));
return;
}
@@ -1488,11 +1500,19 @@
void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status)
throws RemoteException {
- Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status);
+ Log.d(
+ TAG,
+ "onServerPhyRead() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", status="
+ + status);
Integer connId = mServerMap.connIdByAddress(serverIf, address);
if (connId == null) {
- Log.d(TAG, "onServerPhyRead() - no connection to " + address);
+ Log.d(
+ TAG,
+ "onServerPhyRead() - no connection to "
+ + BluetoothUtils.toAnonymizedAddress(address));
return;
}
@@ -1563,7 +1583,7 @@
void onGetGattDb(int connId, List<GattDbElement> db) throws RemoteException {
String address = mClientMap.addressByConnId(connId);
- Log.d(TAG, "onGetGattDb() - address=" + address);
+ Log.d(TAG, "onGetGattDb() - address=" + BluetoothUtils.toAnonymizedAddress(address));
ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId);
if (app == null || app.callback == null) {
@@ -1654,7 +1674,7 @@
Log.d(
TAG,
"onRegisterForNotifications() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", status="
+ status
+ ", registered="
@@ -1669,7 +1689,7 @@
Log.v(
TAG,
"onNotify() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", handle="
+ handle
+ ", length="
@@ -1698,7 +1718,7 @@
Log.v(
TAG,
"onReadCharacteristic() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", status="
+ status
+ ", length="
@@ -1714,14 +1734,17 @@
throws RemoteException {
String address = mClientMap.addressByConnId(connId);
synchronized (mPermits) {
- Log.d(TAG, "onWriteCharacteristic() - increasing permit for address=" + address);
+ Log.d(
+ TAG,
+ "onWriteCharacteristic() - increasing permit for address="
+ + BluetoothUtils.toAnonymizedAddress(address));
mPermits.put(address, -1);
}
Log.v(
TAG,
"onWriteCharacteristic() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", status="
+ status
+ ", length="
@@ -1749,7 +1772,12 @@
void onExecuteCompleted(int connId, int status) throws RemoteException {
String address = mClientMap.addressByConnId(connId);
- Log.v(TAG, "onExecuteCompleted() - address=" + address + ", status=" + status);
+ Log.v(
+ TAG,
+ "onExecuteCompleted() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", status="
+ + status);
ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId);
if (app != null) {
@@ -1763,7 +1791,7 @@
Log.v(
TAG,
"onReadDescriptor() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", status="
+ status
+ ", length="
@@ -1781,7 +1809,7 @@
Log.v(
TAG,
"onWriteDescriptor() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", status="
+ status
+ ", length="
@@ -1800,7 +1828,7 @@
"onReadRemoteRssi() - clientIf="
+ clientIf
+ " address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", rssi="
+ rssi
+ ", status="
@@ -1815,7 +1843,14 @@
void onConfigureMTU(int connId, int status, int mtu) throws RemoteException {
String address = mClientMap.addressByConnId(connId);
- Log.d(TAG, "onConfigureMTU() address=" + address + ", status=" + status + ", mtu=" + mtu);
+ Log.d(
+ TAG,
+ "onConfigureMTU() address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", status="
+ + status
+ + ", mtu="
+ + mtu);
ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId);
if (app != null) {
@@ -2138,7 +2173,7 @@
Log.d(
TAG,
"clientConnect() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", addressType="
+ addressType
+ ", isDirect="
@@ -2178,7 +2213,14 @@
}
mNativeInterface.gattClientConnect(
- clientIf, address, addressType, isDirect, transport, opportunistic, phy, preferredMtu);
+ clientIf,
+ address,
+ addressType,
+ isDirect,
+ transport,
+ opportunistic,
+ phy,
+ preferredMtu);
}
@RequiresPermission(BLUETOOTH_CONNECT)
@@ -2189,7 +2231,12 @@
}
Integer connId = mClientMap.connIdByAddress(clientIf, address);
- Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "clientDisconnect() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
statsLogGattConnectionStateChange(
BluetoothProfile.GATT,
address,
@@ -2214,11 +2261,19 @@
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address);
+ Log.d(
+ TAG,
+ "clientSetPreferredPhy() - no connection to "
+ + BluetoothUtils.toAnonymizedAddress(address));
return;
}
- Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "clientSetPreferredPhy() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
mNativeInterface.gattClientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions);
}
@@ -2231,11 +2286,19 @@
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.d(TAG, "clientReadPhy() - no connection to " + address);
+ Log.d(
+ TAG,
+ "clientReadPhy() - no connection to "
+ + BluetoothUtils.toAnonymizedAddress(address));
return;
}
- Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "clientReadPhy() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
mNativeInterface.gattClientReadPhy(clientIf, address);
}
@@ -2271,7 +2334,7 @@
return;
}
- Log.d(TAG, "refreshDevice() - address=" + address);
+ Log.d(TAG, "refreshDevice() - address=" + BluetoothUtils.toAnonymizedAddress(address));
mNativeInterface.gattClientRefresh(clientIf, address);
}
@@ -2283,12 +2346,21 @@
}
Integer connId = mClientMap.connIdByAddress(clientIf, address);
- Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "discoverServices() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
if (connId != null) {
mNativeInterface.gattClientSearchService(connId, true, 0, 0);
} else {
- Log.e(TAG, "discoverServices() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "discoverServices() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
}
}
@@ -2305,7 +2377,11 @@
mNativeInterface.gattClientDiscoverServiceByUuid(
connId, uuid.getLeastSignificantBits(), uuid.getMostSignificantBits());
} else {
- Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "discoverServiceByUuid() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
}
}
@@ -2321,11 +2397,15 @@
return;
}
- Log.v(TAG, "readCharacteristic() - address=" + address);
+ Log.v(TAG, "readCharacteristic() - address=" + BluetoothUtils.toAnonymizedAddress(address));
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.e(TAG, "readCharacteristic() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "readCharacteristic() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
return;
}
@@ -2358,11 +2438,18 @@
return;
}
- Log.v(TAG, "readUsingCharacteristicUuid() - address=" + address);
+ Log.v(
+ TAG,
+ "readUsingCharacteristicUuid() - address="
+ + BluetoothUtils.toAnonymizedAddress(address));
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "readUsingCharacteristicUuid() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
return;
}
@@ -2401,7 +2488,9 @@
return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
}
- Log.v(TAG, "writeCharacteristic() - address=" + address);
+ Log.v(
+ TAG,
+ "writeCharacteristic() - address=" + BluetoothUtils.toAnonymizedAddress(address));
if (mReliableQueue.contains(address)) {
writeType = 3; // Prepared write
@@ -2409,7 +2498,11 @@
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "writeCharacteristic() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
}
permissionCheck(connId, handle);
@@ -2447,11 +2540,15 @@
return;
}
- Log.v(TAG, "readDescriptor() - address=" + address);
+ Log.v(TAG, "readDescriptor() - address=" + BluetoothUtils.toAnonymizedAddress(address));
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.e(TAG, "readDescriptor() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "readDescriptor() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
return;
}
@@ -2482,11 +2579,15 @@
this, attributionSource, "GattService writeDescriptor")) {
return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
}
- Log.v(TAG, "writeDescriptor() - address=" + address);
+ Log.v(TAG, "writeDescriptor() - address=" + BluetoothUtils.toAnonymizedAddress(address));
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "writeDescriptor() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
}
permissionCheck(connId, handle);
@@ -2502,7 +2603,7 @@
return;
}
- Log.d(TAG, "beginReliableWrite() - address=" + address);
+ Log.d(TAG, "beginReliableWrite() - address=" + BluetoothUtils.toAnonymizedAddress(address));
mReliableQueue.add(address);
}
@@ -2514,7 +2615,12 @@
return;
}
- Log.d(TAG, "endReliableWrite() - address=" + address + " execute: " + execute);
+ Log.d(
+ TAG,
+ "endReliableWrite() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " execute: "
+ + execute);
mReliableQueue.remove(address);
Integer connId = mClientMap.connIdByAddress(clientIf, address);
@@ -2535,11 +2641,20 @@
return;
}
- Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
+ Log.d(
+ TAG,
+ "registerForNotification() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " enable: "
+ + enable);
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId == null) {
- Log.e(TAG, "registerForNotification() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "registerForNotification() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
return;
}
@@ -2565,7 +2680,7 @@
return;
}
- Log.d(TAG, "readRemoteRssi() - address=" + address);
+ Log.d(TAG, "readRemoteRssi() - address=" + BluetoothUtils.toAnonymizedAddress(address));
mNativeInterface.gattClientReadRemoteRssi(clientIf, address);
}
@@ -2576,12 +2691,21 @@
return;
}
- Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu);
+ Log.d(
+ TAG,
+ "configureMTU() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " mtu="
+ + mtu);
Integer connId = mClientMap.connIdByAddress(clientIf, address);
if (connId != null) {
mNativeInterface.gattClientConfigureMTU(connId, mtu);
} else {
- Log.e(TAG, "configureMTU() - No connection for " + address + "...");
+ Log.e(
+ TAG,
+ "configureMTU() - No connection for "
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + "...");
}
}
@@ -2620,7 +2744,7 @@
Log.d(
TAG,
"connectionParameterUpdate() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ " params="
+ connectionPriority
+ " interval="
@@ -2653,7 +2777,7 @@
Log.d(
TAG,
"leConnectionUpdate() - address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", intervals="
+ minInterval
+ "/"
@@ -2887,7 +3011,7 @@
"onClientConnected() connId="
+ connId
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", connected="
+ connected);
@@ -2928,7 +3052,7 @@
"onServerReadCharacteristic() connId="
+ connId
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", handle="
+ handle
+ ", requestId="
@@ -2959,7 +3083,7 @@
"onServerReadDescriptor() connId="
+ connId
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", handle="
+ handle
+ ", requestId="
@@ -2998,7 +3122,7 @@
"onServerWriteCharacteristic() connId="
+ connId
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", handle="
+ handle
+ ", requestId="
@@ -3040,7 +3164,7 @@
"onAttributeWrite() connId="
+ connId
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", handle="
+ handle
+ ", requestId="
@@ -3073,7 +3197,7 @@
"onExecuteWrite() connId="
+ connId
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", transId="
+ transId);
@@ -3195,7 +3319,7 @@
return;
}
- Log.d(TAG, "serverConnect() - address=" + address);
+ Log.d(TAG, "serverConnect() - address=" + BluetoothUtils.toAnonymizedAddress(address));
logServerForegroundInfo(attributionSource.getUid(), isDirect);
@@ -3210,7 +3334,12 @@
}
Integer connId = mServerMap.connIdByAddress(serverIf, address);
- Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "serverDisconnect() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
mNativeInterface.gattServerDisconnect(serverIf, address, connId != null ? connId : 0);
}
@@ -3230,11 +3359,19 @@
Integer connId = mServerMap.connIdByAddress(serverIf, address);
if (connId == null) {
- Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address);
+ Log.d(
+ TAG,
+ "serverSetPreferredPhy() - no connection to "
+ + BluetoothUtils.toAnonymizedAddress(address));
return;
}
- Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "serverSetPreferredPhy() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
mNativeInterface.gattServerSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions);
}
@@ -3247,11 +3384,19 @@
Integer connId = mServerMap.connIdByAddress(serverIf, address);
if (connId == null) {
- Log.d(TAG, "serverReadPhy() - no connection to " + address);
+ Log.d(
+ TAG,
+ "serverReadPhy() - no connection to "
+ + BluetoothUtils.toAnonymizedAddress(address));
return;
}
- Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId);
+ Log.d(
+ TAG,
+ "serverReadPhy() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", connId="
+ + connId);
mNativeInterface.gattServerReadPhy(serverIf, address);
}
@@ -3339,7 +3484,12 @@
return;
}
- Log.v(TAG, "sendResponse() - address=" + address + ", requestId=" + requestId);
+ Log.v(
+ TAG,
+ "sendResponse() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", requestId="
+ + requestId);
int handle = 0;
Integer connId = 0;
@@ -3384,7 +3534,12 @@
return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
}
- Log.v(TAG, "sendNotification() - address=" + address + " handle=" + handle);
+ Log.v(
+ TAG,
+ "sendNotification() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " handle="
+ + handle);
Integer connId = mServerMap.connIdByAddress(serverIf, address);
if (connId == null || connId == 0) {
diff --git a/android/app/src/com/android/bluetooth/hap/HapClientService.java b/android/app/src/com/android/bluetooth/hap/HapClientService.java
index a4896f2..facb63f 100644
--- a/android/app/src/com/android/bluetooth/hap/HapClientService.java
+++ b/android/app/src/com/android/bluetooth/hap/HapClientService.java
@@ -19,6 +19,8 @@
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTING;
import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElseGet;
@@ -76,8 +78,9 @@
private final AdapterService mAdapterService;
private final DatabaseManager mDatabaseManager;
private final Handler mHandler;
+ private final Looper mStateMachinesLooper;
private final HandlerThread mStateMachinesThread;
- private final HapClientNativeInterface mHapClientNativeInterface;
+ private final HapClientNativeInterface mNativeInterface;
@VisibleForTesting
@GuardedBy("mCallbacks")
@@ -114,14 +117,17 @@
}
public HapClientService(AdapterService adapterService) {
- this(adapterService, null);
+ this(adapterService, null, null);
}
@VisibleForTesting
- HapClientService(AdapterService adapterService, HapClientNativeInterface nativeInterface) {
+ HapClientService(
+ AdapterService adapterService,
+ Looper looper,
+ HapClientNativeInterface nativeInterface) {
super(adapterService);
mAdapterService = requireNonNull(adapterService);
- mHapClientNativeInterface =
+ mNativeInterface =
requireNonNullElseGet(
nativeInterface,
() ->
@@ -129,14 +135,19 @@
new HapClientNativeCallback(adapterService, this)));
mDatabaseManager = requireNonNull(mAdapterService.getDatabase());
- // Start handler thread for state machines
- mHandler = new Handler(Looper.getMainLooper());
- mStateMachines.clear();
- mStateMachinesThread = new HandlerThread("HapClientService.StateMachines");
- mStateMachinesThread.start();
+ if (looper == null) {
+ mHandler = new Handler(requireNonNull(Looper.getMainLooper()));
+ mStateMachinesThread = new HandlerThread("HapClientService.StateMachines");
+ mStateMachinesThread.start();
+ mStateMachinesLooper = mStateMachinesThread.getLooper();
+ } else {
+ mHandler = new Handler(looper);
+ mStateMachinesThread = null;
+ mStateMachinesLooper = looper;
+ }
// Initialize native interface
- mHapClientNativeInterface.init();
+ mNativeInterface.init();
// Mark service as started
setHapClient(this);
@@ -162,23 +173,24 @@
synchronized (mStateMachines) {
for (HapClientStateMachine sm : mStateMachines.values()) {
sm.doQuit();
- sm.cleanup();
}
mStateMachines.clear();
}
- try {
- mStateMachinesThread.quitSafely();
- mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS);
- } catch (InterruptedException e) {
- // Do not rethrow as we are shutting down anyway
+ if (mStateMachinesThread != null) {
+ try {
+ mStateMachinesThread.quitSafely();
+ mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS);
+ } catch (InterruptedException e) {
+ // Do not rethrow as we are shutting down anyway
+ }
}
// Unregister Handler and stop all queued messages.
mHandler.removeCallbacksAndMessages(null);
// Cleanup GATT interface
- mHapClientNativeInterface.cleanup();
+ mNativeInterface.cleanup();
// Cleanup the internals
mDeviceCurrentPresetMap.clear();
@@ -233,7 +245,6 @@
}
Log.i(TAG, "removeStateMachine: removing state machine for device: " + device);
sm.doQuit();
- sm.cleanup();
mStateMachines.remove(device);
}
}
@@ -423,7 +434,7 @@
if (smConnect == null) {
Log.e(TAG, "Cannot connect to " + device + " : no state machine");
}
- smConnect.sendMessage(HapClientStateMachine.CONNECT);
+ smConnect.sendMessage(HapClientStateMachine.MESSAGE_CONNECT);
}
return true;
@@ -444,7 +455,7 @@
synchronized (mStateMachines) {
HapClientStateMachine sm = mStateMachines.get(device);
if (sm != null) {
- sm.sendMessage(HapClientStateMachine.DISCONNECT);
+ sm.sendMessage(HapClientStateMachine.MESSAGE_DISCONNECT);
}
}
@@ -470,12 +481,7 @@
return null;
}
Log.d(TAG, "Creating a new state machine for " + device);
- sm =
- HapClientStateMachine.make(
- device,
- this,
- mHapClientNativeInterface,
- mStateMachinesThread.getLooper());
+ sm = new HapClientStateMachine(this, device, mNativeInterface, mStateMachinesLooper);
mStateMachines.put(device, sm);
return sm;
}
@@ -542,7 +548,7 @@
return;
}
- mHapClientNativeInterface.selectActivePreset(device, presetIndex);
+ mNativeInterface.selectActivePreset(device, presetIndex);
}
@VisibleForTesting
@@ -558,23 +564,23 @@
return;
}
- mHapClientNativeInterface.groupSelectActivePreset(groupId, presetIndex);
+ mNativeInterface.groupSelectActivePreset(groupId, presetIndex);
}
void switchToNextPreset(BluetoothDevice device) {
- mHapClientNativeInterface.nextActivePreset(device);
+ mNativeInterface.nextActivePreset(device);
}
void switchToNextPresetForGroup(int groupId) {
- mHapClientNativeInterface.groupNextActivePreset(groupId);
+ mNativeInterface.groupNextActivePreset(groupId);
}
void switchToPreviousPreset(BluetoothDevice device) {
- mHapClientNativeInterface.previousActivePreset(device);
+ mNativeInterface.previousActivePreset(device);
}
void switchToPreviousPresetForGroup(int groupId) {
- mHapClientNativeInterface.groupPreviousActivePreset(groupId);
+ mNativeInterface.groupPreviousActivePreset(groupId);
}
BluetoothHapPresetInfo getPresetInfo(BluetoothDevice device, int presetIndex) {
@@ -585,7 +591,7 @@
/* We want native to be called for PTS testing even we have all
* the data in the cache here
*/
- mHapClientNativeInterface.getPresetInfo(device, presetIndex);
+ mNativeInterface.getPresetInfo(device, presetIndex);
}
List<BluetoothHapPresetInfo> current_presets = mPresetsMap.get(device);
if (current_presets != null) {
@@ -614,20 +620,19 @@
}
private int stackEventPresetInfoReasonToProfileStatus(int statusCode) {
- switch (statusCode) {
- case HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO:
- return BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST;
- case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE:
- return BluetoothStatusCodes.REASON_REMOTE_REQUEST;
- case HapClientStackEvent.PRESET_INFO_REASON_PRESET_DELETED:
- return BluetoothStatusCodes.REASON_REMOTE_REQUEST;
- case HapClientStackEvent.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED:
- return BluetoothStatusCodes.REASON_REMOTE_REQUEST;
- case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE:
- return BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST;
- default:
- return BluetoothStatusCodes.ERROR_UNKNOWN;
- }
+ return switch (statusCode) {
+ case HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO ->
+ BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST;
+ case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE ->
+ BluetoothStatusCodes.REASON_REMOTE_REQUEST;
+ case HapClientStackEvent.PRESET_INFO_REASON_PRESET_DELETED ->
+ BluetoothStatusCodes.REASON_REMOTE_REQUEST;
+ case HapClientStackEvent.PRESET_INFO_REASON_PRESET_AVAILABILITY_CHANGED ->
+ BluetoothStatusCodes.REASON_REMOTE_REQUEST;
+ case HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_REQUEST_RESPONSE ->
+ BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST;
+ default -> BluetoothStatusCodes.ERROR_UNKNOWN;
+ };
}
private void notifyPresetInfoChanged(BluetoothDevice device, int infoReason) {
@@ -643,24 +648,23 @@
}
private int stackEventStatusToProfileStatus(int statusCode) {
- switch (statusCode) {
- case HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED:
- return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED;
- case HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED:
- return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED;
- case HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE:
- return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED;
- case HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH:
- return BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG;
- case HapClientStackEvent.STATUS_INVALID_PRESET_INDEX:
- return BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX;
- case HapClientStackEvent.STATUS_GROUP_OPERATION_NOT_SUPPORTED:
- return BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED;
- case HapClientStackEvent.STATUS_PROCEDURE_ALREADY_IN_PROGRESS:
- return BluetoothStatusCodes.ERROR_UNKNOWN;
- default:
- return BluetoothStatusCodes.ERROR_UNKNOWN;
- }
+ return switch (statusCode) {
+ case HapClientStackEvent.STATUS_SET_NAME_NOT_ALLOWED ->
+ BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED;
+ case HapClientStackEvent.STATUS_OPERATION_NOT_SUPPORTED ->
+ BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED;
+ case HapClientStackEvent.STATUS_OPERATION_NOT_POSSIBLE ->
+ BluetoothStatusCodes.ERROR_REMOTE_OPERATION_REJECTED;
+ case HapClientStackEvent.STATUS_INVALID_PRESET_NAME_LENGTH ->
+ BluetoothStatusCodes.ERROR_HAP_PRESET_NAME_TOO_LONG;
+ case HapClientStackEvent.STATUS_INVALID_PRESET_INDEX ->
+ BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX;
+ case HapClientStackEvent.STATUS_GROUP_OPERATION_NOT_SUPPORTED ->
+ BluetoothStatusCodes.ERROR_REMOTE_OPERATION_NOT_SUPPORTED;
+ case HapClientStackEvent.STATUS_PROCEDURE_ALREADY_IN_PROGRESS ->
+ BluetoothStatusCodes.ERROR_UNKNOWN;
+ default -> BluetoothStatusCodes.ERROR_UNKNOWN;
+ };
}
private boolean isPresetIndexValid(BluetoothDevice device, int presetIndex) {
@@ -717,7 +721,7 @@
// WARNING: We should check cache if preset exists and is writable, but then we would still
// need a way to trigger this action with an invalid index or on a non-writable
// preset for tests purpose.
- mHapClientNativeInterface.setPresetName(device, presetIndex, name);
+ mNativeInterface.setPresetName(device, presetIndex, name);
}
@VisibleForTesting
@@ -733,7 +737,7 @@
return;
}
- mHapClientNativeInterface.groupSetPresetName(groupId, presetIndex, name);
+ mNativeInterface.groupSetPresetName(groupId, presetIndex, name);
}
@Override
@@ -912,8 +916,7 @@
if (sm == null) {
if (stackEvent.type == HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
switch (stackEvent.valueInt1) {
- case HapClientStackEvent.CONNECTION_STATE_CONNECTED,
- HapClientStackEvent.CONNECTION_STATE_CONNECTING -> {
+ case STATE_CONNECTED, STATE_CONNECTING -> {
sm = getOrCreateStateMachine(device);
}
default -> {}
@@ -924,7 +927,7 @@
Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent);
return;
}
- sm.sendMessage(HapClientStateMachine.STACK_EVENT, stackEvent);
+ sm.sendMessage(HapClientStateMachine.MESSAGE_STACK_EVENT, stackEvent);
}
}
diff --git a/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java b/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java
index 841baaf..a0e978e 100644
--- a/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java
+++ b/android/app/src/com/android/bluetooth/hap/HapClientStackEvent.java
@@ -17,6 +17,8 @@
package com.android.bluetooth.hap;
+import static android.bluetooth.BluetoothProfile.getConnectionStateName;
+
import android.bluetooth.BluetoothDevice;
import android.bluetooth.IBluetoothHapClient;
@@ -40,12 +42,6 @@
public static final int EVENT_TYPE_ON_PRESET_NAME_SET_ERROR = 7;
public static final int EVENT_TYPE_ON_PRESET_INFO_ERROR = 8;
- // Connection state values as defined in bt_has.h
- static final int CONNECTION_STATE_DISCONNECTED = 0;
- static final int CONNECTION_STATE_CONNECTING = 1;
- static final int CONNECTION_STATE_CONNECTED = 2;
- static final int CONNECTION_STATE_DISCONNECTING = 3;
-
// Possible operation results
/* WARNING: Matches status codes defined in bta_has.h */
static final int STATUS_NO_ERROR = 0;
@@ -117,7 +113,7 @@
private String eventTypeValueInt1ToString(int type, int value) {
switch (type) {
case EVENT_TYPE_CONNECTION_STATE_CHANGED:
- return "{state: " + connectionStateValueToString(value) + "}";
+ return "{state: " + getConnectionStateName(value) + "}";
case EVENT_TYPE_DEVICE_AVAILABLE:
return "{features: " + featuresToString(value) + "}";
case EVENT_TYPE_DEVICE_FEATURES:
@@ -181,21 +177,6 @@
}
}
- private String connectionStateValueToString(int value) {
- switch (value) {
- case CONNECTION_STATE_DISCONNECTED:
- return "CONNECTION_STATE_DISCONNECTED";
- case CONNECTION_STATE_CONNECTING:
- return "CONNECTION_STATE_CONNECTING";
- case CONNECTION_STATE_CONNECTED:
- return "CONNECTION_STATE_CONNECTED";
- case CONNECTION_STATE_DISCONNECTING:
- return "CONNECTION_STATE_DISCONNECTING";
- default:
- return "CONNECTION_STATE_UNKNOWN!";
- }
- }
-
private String statusCodeValueToString(int value) {
switch (value) {
case STATUS_NO_ERROR:
diff --git a/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java b/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java
index e0b6ded..4695103 100644
--- a/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java
+++ b/android/app/src/com/android/bluetooth/hap/HapClientStateMachine.java
@@ -15,23 +15,39 @@
* limitations under the License.
*/
-/**
- * Bluetooth Hap Client StateMachine. There is one instance per remote device. - "Disconnected" and
- * "Connected" are steady states. - "Connecting" and "Disconnecting" are transient states until the
- * connection / disconnection is completed.
- *
- * <p>(Disconnected) | ^ CONNECT | | DISCONNECTED V | (Connecting)<--->(Disconnecting) | ^ CONNECTED
- * | | DISCONNECT V | (Connected) NOTES: - If state machine is in "Connecting" state and the remote
- * device sends DISCONNECT request, the state machine transitions to "Disconnecting" state. -
- * Similarly, if the state machine is in "Disconnecting" state and the remote device sends CONNECT
- * request, the state machine transitions to "Connecting" state.
- *
- * <p>DISCONNECT (Connecting) ---------------> (Disconnecting) <--------------- CONNECT
- */
+// Bluetooth Hap Client StateMachine. There is one instance per remote device.
+// - "Disconnected" and "Connected" are steady states.
+// - "Connecting" and "Disconnecting" are transient states until the
+// connection / disconnection is completed.
+
+// (Disconnected)
+// | ^
+// CONNECT | | DISCONNECTED
+// V |
+// (Connecting)<--->(Disconnecting)
+// | ^
+// CONNECTED | | DISCONNECT
+// V |
+// (Connected)
+// NOTES:
+// - If state machine is in "Connecting" state and the remote device sends
+// DISCONNECT request, the state machine transitions to "Disconnecting" state.
+// - Similarly, if the state machine is in "Disconnecting" state and the remote device
+// sends CONNECT request, the state machine transitions to "Connecting" state.
+
+// DISCONNECT
+// (Connecting) ---------------> (Disconnecting)
+// <---------------
+// CONNECT
package com.android.bluetooth.hap;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
+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 android.bluetooth.BluetoothProfile.getConnectionStateName;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
@@ -49,40 +65,40 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.time.Duration;
import java.util.Scanner;
final class HapClientStateMachine extends StateMachine {
- static final int CONNECT = 1;
- static final int DISCONNECT = 2;
- @VisibleForTesting static final int STACK_EVENT = 101;
- private static final String TAG = "HapClientStateMachine";
- @VisibleForTesting static final int CONNECT_TIMEOUT = 201;
+ private static final String TAG = HapClientStateMachine.class.getSimpleName();
- // NOTE: the value is not "final" - it is modified in the unit tests
- @VisibleForTesting static int sConnectTimeoutMs = 30000; // 30s
+ static final int MESSAGE_CONNECT = 1;
+ static final int MESSAGE_DISCONNECT = 2;
+ static final int MESSAGE_STACK_EVENT = 101;
+ @VisibleForTesting static final int MESSAGE_CONNECT_TIMEOUT = 201;
+
+ @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30);
private final Disconnected mDisconnected;
private final Connecting mConnecting;
private final Disconnecting mDisconnecting;
private final Connected mConnected;
- private int mConnectionState = BluetoothProfile.STATE_DISCONNECTED;
+
+ private int mConnectionState = STATE_DISCONNECTED;
private int mLastConnectionState = -1;
private final HapClientService mService;
private final HapClientNativeInterface mNativeInterface;
-
private final BluetoothDevice mDevice;
HapClientStateMachine(
- BluetoothDevice device,
HapClientService svc,
+ BluetoothDevice device,
HapClientNativeInterface gattInterface,
Looper looper) {
super(TAG, looper);
mDevice = device;
mService = svc;
mNativeInterface = gattInterface;
-
mDisconnected = new Disconnected();
mConnecting = new Connecting();
mDisconnecting = new Disconnecting();
@@ -94,61 +110,24 @@
addState(mConnected);
setInitialState(mDisconnected);
- }
-
- static HapClientStateMachine make(
- BluetoothDevice device,
- HapClientService svc,
- HapClientNativeInterface gattInterface,
- Looper looper) {
- Log.i(TAG, "make for device " + device);
- HapClientStateMachine hearingAccessSm =
- new HapClientStateMachine(device, svc, gattInterface, looper);
- hearingAccessSm.start();
- return hearingAccessSm;
+ start();
}
private static String messageWhatToString(int what) {
- switch (what) {
- case CONNECT:
- return "CONNECT";
- case DISCONNECT:
- return "DISCONNECT";
- case STACK_EVENT:
- return "STACK_EVENT";
- case CONNECT_TIMEOUT:
- return "CONNECT_TIMEOUT";
- default:
- break;
- }
- return Integer.toString(what);
- }
-
- private static String profileStateToString(int state) {
- switch (state) {
- case BluetoothProfile.STATE_DISCONNECTED:
- return "DISCONNECTED";
- case BluetoothProfile.STATE_CONNECTING:
- return "CONNECTING";
- case BluetoothProfile.STATE_CONNECTED:
- return "CONNECTED";
- case BluetoothProfile.STATE_DISCONNECTING:
- return "DISCONNECTING";
- default:
- break;
- }
- return Integer.toString(state);
+ return switch (what) {
+ case MESSAGE_CONNECT -> "CONNECT";
+ case MESSAGE_DISCONNECT -> "DISCONNECT";
+ case MESSAGE_STACK_EVENT -> "STACK_EVENT";
+ case MESSAGE_CONNECT_TIMEOUT -> "CONNECT_TIMEOUT";
+ default -> Integer.toString(what);
+ };
}
public void doQuit() {
- log("doQuit for device " + mDevice);
+ Log.d(TAG, "doQuit for " + mDevice);
quitNow();
}
- public void cleanup() {
- log("cleanup for device " + mDevice);
- }
-
int getConnectionState() {
return mConnectionState;
}
@@ -158,24 +137,22 @@
}
synchronized boolean isConnected() {
- return (getConnectionState() == BluetoothProfile.STATE_CONNECTED);
+ return (getConnectionState() == STATE_CONNECTED);
}
- // This method does not check for error condition (newState == prevState)
- private void broadcastConnectionState(int newState, int prevState) {
- log(
- "Connection state "
- + mDevice
- + ": "
- + profileStateToString(prevState)
+ private void broadcastConnectionState() {
+ Log.d(
+ TAG,
+ ("Connection state " + mDevice + ": ")
+ + getConnectionStateName(mLastConnectionState)
+ "->"
- + profileStateToString(newState));
+ + getConnectionStateName(mConnectionState));
- mService.connectionStateChanged(mDevice, prevState, newState);
+ mService.connectionStateChanged(mDevice, mLastConnectionState, mConnectionState);
Intent intent =
new Intent(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED)
- .putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState)
- .putExtra(BluetoothProfile.EXTRA_STATE, newState)
+ .putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, mLastConnectionState)
+ .putExtra(BluetoothProfile.EXTRA_STATE, mConnectionState)
.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice)
.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
@@ -202,86 +179,60 @@
scanner.close();
}
- @Override
- protected void log(String msg) {
- super.log(msg);
- }
-
@VisibleForTesting
class Disconnected extends State {
+ private final String mStateLog = "Disconnected(" + mDevice + "): ";
+
@Override
public void enter() {
- Log.i(
- TAG,
- "Enter Disconnected("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- mConnectionState = BluetoothProfile.STATE_DISCONNECTED;
+ Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what));
- removeDeferredMessages(DISCONNECT);
+ removeDeferredMessages(MESSAGE_DISCONNECT);
- if (mLastConnectionState != -1) {
- // Don't broadcast during startup
- broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, mLastConnectionState);
+ mConnectionState = STATE_DISCONNECTED;
+ if (mLastConnectionState != -1) { // Don't broadcast during startup
+ broadcastConnectionState();
}
}
@Override
public void exit() {
- log(
- "Exit Disconnected("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED;
+ Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ mLastConnectionState = STATE_DISCONNECTED;
}
@Override
public boolean processMessage(Message message) {
- log(
- "Disconnected: process message("
- + mDevice
- + "): "
- + messageWhatToString(message.what));
+ Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what));
switch (message.what) {
- case CONNECT:
- log("Connecting to " + mDevice);
+ case MESSAGE_CONNECT -> {
if (!mNativeInterface.connectHapClient(mDevice)) {
- Log.e(TAG, "Disconnected: error connecting to " + mDevice);
+ Log.e(TAG, mStateLog + "native cannot connect");
break;
}
if (mService.okToConnect(mDevice)) {
transitionTo(mConnecting);
} else {
- // Reject the request and stay in Disconnected state
- Log.w(
- TAG,
- "Outgoing HearingAccess Connecting request rejected: " + mDevice);
+ Log.w(TAG, mStateLog + "outgoing connect request rejected");
}
- break;
- case DISCONNECT:
- Log.d(TAG, "Disconnected: DISCONNECT: call native disconnect for " + mDevice);
+ }
+ case MESSAGE_DISCONNECT -> {
mNativeInterface.disconnectHapClient(mDevice);
- break;
- case STACK_EVENT:
+ }
+ case MESSAGE_STACK_EVENT -> {
HapClientStackEvent event = (HapClientStackEvent) message.obj;
- Log.d(TAG, "Disconnected: stack event: " + event);
- if (!mDevice.equals(event.device)) {
- Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event);
- }
switch (event.type) {
- case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
+ case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> {
processConnectionEvent(event.valueInt1);
- break;
- default:
- Log.e(TAG, "Disconnected: ignoring stack event: " + event);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event);
}
- break;
- default:
+ }
+ default -> {
+ Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what));
return NOT_HANDLED;
+ }
}
return HANDLED;
}
@@ -289,114 +240,83 @@
// in Disconnected state
private void processConnectionEvent(int state) {
switch (state) {
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED:
- Log.w(TAG, "Ignore HearingAccess DISCONNECTED event: " + mDevice);
- break;
- case HapClientStackEvent.CONNECTION_STATE_CONNECTING:
+ case STATE_CONNECTING -> {
if (mService.okToConnect(mDevice)) {
- Log.i(
- TAG,
- "Incoming HearingAccess Connecting request accepted: " + mDevice);
+ Log.i(TAG, mStateLog + "Incoming connecting request accepted");
transitionTo(mConnecting);
} else {
- // Reject the connection and stay in Disconnected state itself
- Log.w(
- TAG,
- "Incoming HearingAccess Connecting request rejected: " + mDevice);
+ Log.w(TAG, mStateLog + "Incoming connecting request rejected");
mNativeInterface.disconnectHapClient(mDevice);
}
- break;
- case HapClientStackEvent.CONNECTION_STATE_CONNECTED:
+ }
+ case STATE_CONNECTED -> {
Log.w(TAG, "HearingAccess Connected from Disconnected state: " + mDevice);
if (mService.okToConnect(mDevice)) {
- Log.i(TAG, "Incoming HearingAccess Connected request accepted: " + mDevice);
+ Log.w(TAG, mStateLog + "Incoming connected transition accepted");
transitionTo(mConnected);
} else {
- // Reject the connection and stay in Disconnected state itself
- Log.w(TAG, "Incoming HearingAccess Connected request rejected: " + mDevice);
+ Log.w(TAG, mStateLog + "Incoming connected transition rejected");
mNativeInterface.disconnectHapClient(mDevice);
}
- break;
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING:
- Log.w(TAG, "Ignore HearingAccess DISCONNECTING event: " + mDevice);
- break;
- default:
- Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "Incorrect state: " + state);
}
}
}
@VisibleForTesting
class Connecting extends State {
+ private final String mStateLog = "Connecting(" + mDevice + "): ";
+
@Override
public void enter() {
- Log.i(
- TAG,
- "Enter Connecting("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs);
- mConnectionState = BluetoothProfile.STATE_CONNECTING;
- broadcastConnectionState(BluetoothProfile.STATE_CONNECTING, mLastConnectionState);
+ Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis());
+ mConnectionState = STATE_CONNECTING;
+ broadcastConnectionState();
}
@Override
public void exit() {
- log(
- "Exit Connecting("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- mLastConnectionState = BluetoothProfile.STATE_CONNECTING;
- removeMessages(CONNECT_TIMEOUT);
+ Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ mLastConnectionState = STATE_CONNECTING;
+ removeMessages(MESSAGE_CONNECT_TIMEOUT);
}
@Override
public boolean processMessage(Message message) {
- log(
- "Connecting: process message("
- + mDevice
- + "): "
- + messageWhatToString(message.what));
+ Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what));
switch (message.what) {
- case CONNECT:
- deferMessage(message);
- break;
- case CONNECT_TIMEOUT:
- Log.w(TAG, "Connecting connection timeout: " + mDevice);
+ case MESSAGE_CONNECT -> deferMessage(message);
+ case MESSAGE_CONNECT_TIMEOUT -> {
+ Log.w(TAG, mStateLog + "connection timeout");
mNativeInterface.disconnectHapClient(mDevice);
HapClientStackEvent disconnectEvent =
new HapClientStackEvent(
HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
disconnectEvent.device = mDevice;
- disconnectEvent.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTED;
- sendMessage(STACK_EVENT, disconnectEvent);
- break;
- case DISCONNECT:
- log("Connecting: connection canceled to " + mDevice);
+ disconnectEvent.valueInt1 = STATE_DISCONNECTED;
+ sendMessage(MESSAGE_STACK_EVENT, disconnectEvent);
+ }
+ case MESSAGE_DISCONNECT -> {
+ Log.d(TAG, mStateLog + "connection canceled");
mNativeInterface.disconnectHapClient(mDevice);
transitionTo(mDisconnected);
- break;
- case STACK_EVENT:
+ }
+ case MESSAGE_STACK_EVENT -> {
HapClientStackEvent event = (HapClientStackEvent) message.obj;
- log("Connecting: stack event: " + event);
- if (!mDevice.equals(event.device)) {
- Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event);
- }
switch (event.type) {
- case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
+ case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> {
processConnectionEvent(event.valueInt1);
- break;
- default:
- Log.e(TAG, "Connecting: ignoring stack event: " + event);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event);
}
- break;
- default:
+ }
+ default -> {
+ Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what));
return NOT_HANDLED;
+ }
}
return HANDLED;
}
@@ -404,98 +324,69 @@
// in Connecting state
private void processConnectionEvent(int state) {
switch (state) {
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED:
- Log.w(TAG, "Connecting device disconnected: " + mDevice);
+ case STATE_DISCONNECTED -> {
+ Log.i(TAG, mStateLog + "device disconnected");
transitionTo(mDisconnected);
- break;
- case HapClientStackEvent.CONNECTION_STATE_CONNECTED:
- transitionTo(mConnected);
- break;
- case HapClientStackEvent.CONNECTION_STATE_CONNECTING:
- break;
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING:
- Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice);
+ }
+ case STATE_CONNECTED -> transitionTo(mConnected);
+ case STATE_DISCONNECTING -> {
+ Log.i(TAG, mStateLog + "device disconnecting");
transitionTo(mDisconnecting);
- break;
- default:
- Log.e(TAG, "Incorrect state: " + state);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "Incorrect state: " + state);
}
}
}
@VisibleForTesting
class Disconnecting extends State {
+ private final String mStateLog = "Disconnecting(" + mDevice + "): ";
+
@Override
public void enter() {
- Log.i(
- TAG,
- "Enter Disconnecting("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs);
- mConnectionState = BluetoothProfile.STATE_DISCONNECTING;
- broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTING, mLastConnectionState);
+ Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ sendMessageDelayed(MESSAGE_CONNECT_TIMEOUT, CONNECT_TIMEOUT.toMillis());
+ mConnectionState = STATE_DISCONNECTING;
+ broadcastConnectionState();
}
@Override
public void exit() {
- log(
- "Exit Disconnecting("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING;
- removeMessages(CONNECT_TIMEOUT);
+ Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ mLastConnectionState = STATE_DISCONNECTING;
+ removeMessages(MESSAGE_CONNECT_TIMEOUT);
}
@Override
public boolean processMessage(Message message) {
- log(
- "Disconnecting: process message("
- + mDevice
- + "): "
- + messageWhatToString(message.what));
+ Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what));
switch (message.what) {
- case CONNECT:
- deferMessage(message);
- break;
- case CONNECT_TIMEOUT:
- {
- Log.w(TAG, "Disconnecting connection timeout: " + mDevice);
- mNativeInterface.disconnectHapClient(mDevice);
+ case MESSAGE_CONNECT, MESSAGE_DISCONNECT -> deferMessage(message);
+ case MESSAGE_CONNECT_TIMEOUT -> {
+ Log.w(TAG, mStateLog + "connection timeout");
+ mNativeInterface.disconnectHapClient(mDevice);
- HapClientStackEvent disconnectEvent =
- new HapClientStackEvent(
- HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- disconnectEvent.device = mDevice;
- disconnectEvent.valueInt1 =
- HapClientStackEvent.CONNECTION_STATE_DISCONNECTED;
- sendMessage(STACK_EVENT, disconnectEvent);
- break;
- }
- case DISCONNECT:
- deferMessage(message);
- break;
- case STACK_EVENT:
+ HapClientStackEvent disconnectEvent =
+ new HapClientStackEvent(
+ HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ disconnectEvent.device = mDevice;
+ disconnectEvent.valueInt1 = STATE_DISCONNECTED;
+ sendMessage(MESSAGE_STACK_EVENT, disconnectEvent);
+ }
+ case MESSAGE_STACK_EVENT -> {
HapClientStackEvent event = (HapClientStackEvent) message.obj;
- log("Disconnecting: stack event: " + event);
- if (!mDevice.equals(event.device)) {
- Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event);
- }
switch (event.type) {
- case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
+ case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED -> {
processConnectionEvent(event.valueInt1);
- break;
- default:
- Log.e(TAG, "Disconnecting: ignoring stack event: " + event);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event);
}
- break;
- default:
+ }
+ default -> {
+ Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what));
return NOT_HANDLED;
+ }
}
return HANDLED;
}
@@ -503,105 +394,79 @@
// in Disconnecting state
private void processConnectionEvent(int state) {
switch (state) {
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED:
- Log.i(TAG, "Disconnected: " + mDevice);
+ case STATE_DISCONNECTED -> {
+ Log.i(TAG, mStateLog + "Disconnected");
transitionTo(mDisconnected);
- break;
- case HapClientStackEvent.CONNECTION_STATE_CONNECTED:
+ }
+ case STATE_CONNECTED -> {
if (mService.okToConnect(mDevice)) {
- Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice);
+ Log.w(TAG, mStateLog + "interrupted: device is connected");
transitionTo(mConnected);
} else {
// Reject the connection and stay in Disconnecting state
- Log.w(TAG, "Incoming HearingAccess Connected request rejected: " + mDevice);
+ Log.w(TAG, mStateLog + "Incoming connect request rejected");
mNativeInterface.disconnectHapClient(mDevice);
}
- break;
- case HapClientStackEvent.CONNECTION_STATE_CONNECTING:
+ }
+ case STATE_CONNECTING -> {
if (mService.okToConnect(mDevice)) {
- Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice);
+ Log.i(TAG, mStateLog + "interrupted: device try to reconnect");
transitionTo(mConnecting);
} else {
// Reject the connection and stay in Disconnecting state
- Log.w(
- TAG,
- "Incoming HearingAccess Connecting request rejected: " + mDevice);
+ Log.w(TAG, mStateLog + "Incoming connecting request rejected");
mNativeInterface.disconnectHapClient(mDevice);
}
- break;
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING:
- break;
- default:
- Log.e(TAG, "Incorrect state: " + state);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "Incorrect state: " + state);
}
}
}
@VisibleForTesting
class Connected extends State {
+ private final String mStateLog = "Connected(" + mDevice + "): ";
+
@Override
public void enter() {
- Log.i(
- TAG,
- "Enter Connected("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- mConnectionState = BluetoothProfile.STATE_CONNECTED;
- removeDeferredMessages(CONNECT);
- broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState);
+ Log.i(TAG, "Enter " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ removeDeferredMessages(MESSAGE_CONNECT);
+ mConnectionState = STATE_CONNECTED;
+ broadcastConnectionState();
}
@Override
public void exit() {
- log(
- "Exit Connected("
- + mDevice
- + "): "
- + messageWhatToString(getCurrentMessage().what));
- mLastConnectionState = BluetoothProfile.STATE_CONNECTED;
+ Log.d(TAG, "Exit " + mStateLog + messageWhatToString(getCurrentMessage().what));
+ mLastConnectionState = STATE_CONNECTED;
}
@Override
public boolean processMessage(Message message) {
- log(
- "Connected: process message("
- + mDevice
- + "): "
- + messageWhatToString(message.what));
+ Log.d(TAG, mStateLog + "processMessage: " + messageWhatToString(message.what));
switch (message.what) {
- case CONNECT:
- Log.w(TAG, "Connected: CONNECT ignored: " + mDevice);
- break;
- case DISCONNECT:
- log("Disconnecting from " + mDevice);
+ case MESSAGE_DISCONNECT -> {
if (!mNativeInterface.disconnectHapClient(mDevice)) {
// If error in the native stack, transition directly to Disconnected state.
- Log.e(TAG, "Connected: error disconnecting from " + mDevice);
+ Log.e(TAG, mStateLog + "native cannot disconnect");
transitionTo(mDisconnected);
break;
}
transitionTo(mDisconnecting);
- break;
- case STACK_EVENT:
+ }
+ case MESSAGE_STACK_EVENT -> {
HapClientStackEvent event = (HapClientStackEvent) message.obj;
- log("Connected: stack event: " + event);
- if (!mDevice.equals(event.device)) {
- Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event);
- }
switch (event.type) {
- case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED:
- processConnectionEvent(event.valueInt1);
- break;
- default:
- Log.e(TAG, "Connected: ignoring stack event: " + event);
- break;
+ case HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED ->
+ processConnectionEvent(event.valueInt1);
+ default -> Log.e(TAG, mStateLog + "ignoring stack event: " + event);
}
- break;
- default:
+ }
+ default -> {
+ Log.e(TAG, mStateLog + "not handled: " + messageWhatToString(message.what));
return NOT_HANDLED;
+ }
}
return HANDLED;
}
@@ -609,17 +474,15 @@
// in Connected state
private void processConnectionEvent(int state) {
switch (state) {
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTED:
- Log.i(TAG, "Disconnected from " + mDevice + " but still in Allowlist");
+ case STATE_DISCONNECTED -> {
+ Log.i(TAG, mStateLog + "Disconnected but still in allowlist");
transitionTo(mDisconnected);
- break;
- case HapClientStackEvent.CONNECTION_STATE_DISCONNECTING:
- Log.i(TAG, "Disconnecting from " + mDevice);
+ }
+ case STATE_DISCONNECTING -> {
+ Log.i(TAG, mStateLog + "Disconnecting");
transitionTo(mDisconnecting);
- break;
- default:
- Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state);
- break;
+ }
+ default -> Log.e(TAG, mStateLog + "Incorrect state: " + state);
}
}
}
diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 52cc028..c706e2c 100644
--- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -2389,6 +2389,15 @@
Log.d(TAG, "Processing command: " + atString);
if (processAndroidAtSinkAudioPolicy(args, device)) {
mNativeInterface.atResponseCode(device, HeadsetHalConstants.AT_RESPONSE_OK, 0);
+ if (getHfpCallAudioPolicy().getActiveDevicePolicyAfterConnection()
+ == BluetoothSinkAudioPolicy.POLICY_NOT_ALLOWED
+ && mDevice.equals(mHeadsetService.getActiveDevice())) {
+ Log.d(
+ TAG,
+ "Remove the active device because the active device policy after"
+ + " connection is not allowed");
+ mHeadsetService.setActiveDevice(null);
+ }
} else {
Log.w(TAG, "Invalid SinkAudioPolicy parameters!");
mNativeInterface.atResponseCode(
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 7438921..a7e3bff 100644
--- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java
+++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java
@@ -16,6 +16,7 @@
package com.android.bluetooth.le_scan;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothProtoEnums;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
@@ -104,6 +105,7 @@
public int scanMode;
public int scanCallbackType;
public StringBuilder filterString;
+ @Nullable public String attributionTag;
LastScan(
long timestamp,
@@ -112,7 +114,8 @@
boolean isCallbackScan,
int scannerId,
int scanMode,
- int scanCallbackType) {
+ int scanCallbackType,
+ @Nullable String attributionTag) {
this.duration = 0;
this.timestamp = timestamp;
this.reportDelayMillis = reportDelayMillis;
@@ -126,6 +129,7 @@
this.isAutoBatchScan = false;
this.scanMode = scanMode;
this.scanCallbackType = scanCallbackType;
+ this.attributionTag = attributionTag;
this.results = 0;
this.scannerId = scannerId;
this.suspendDuration = 0;
@@ -239,7 +243,8 @@
List<ScanFilter> filters,
boolean isFilterScan,
boolean isCallbackScan,
- int scannerId) {
+ int scannerId,
+ @Nullable String attributionTag) {
LastScan existingScan = getScanFromScannerId(scannerId);
if (existingScan != null) {
return;
@@ -255,7 +260,8 @@
isCallbackScan,
scannerId,
settings.getScanMode(),
- settings.getCallbackType());
+ settings.getCallbackType(),
+ attributionTag);
if (settings != null) {
scan.isOpportunisticScan = scan.scanMode == ScanSettings.SCAN_MODE_OPPORTUNISTIC;
scan.isBackgroundScan =
@@ -1065,6 +1071,9 @@
}
sb.append(scan.results).append(" results");
sb.append(" (").append(scan.scannerId).append(") ");
+ if (scan.attributionTag != null) {
+ sb.append(" [").append(scan.attributionTag).append("] ");
+ }
if (scan.isCallbackScan) {
sb.append("CB ");
} else {
diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java
index 09f3626..a6470bd 100644
--- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java
+++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java
@@ -28,6 +28,7 @@
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;
@@ -342,7 +343,7 @@
+ ", addressType="
+ addressType
+ ", address="
- + address
+ + BluetoothUtils.toAnonymizedAddress(address)
+ ", primaryPhy="
+ primaryPhy
+ ", secondaryPhy="
@@ -1245,7 +1246,13 @@
if (cbApp != null) {
isCallbackScan = cbApp.mCallback != null;
}
- app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId);
+ app.recordScanStart(
+ settings,
+ filters,
+ isFilteredScan,
+ isCallbackScan,
+ scannerId,
+ cbApp == null ? null : cbApp.mAttributionTag);
}
mScanManager.startScan(scanClient);
@@ -1352,7 +1359,12 @@
scanClient.stats = scanStats;
boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty();
scanStats.recordScanStart(
- piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId);
+ piInfo.settings,
+ piInfo.filters,
+ isFilteredScan,
+ false,
+ scannerId,
+ app.mAttributionTag);
}
mScanManager.startScan(scanClient);
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java
index e5324ae..4e81095 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java
@@ -16,56 +16,44 @@
package com.android.bluetooth.vc;
-import android.bluetooth.BluetoothVolumeControl;
import android.util.Log;
import com.android.bluetooth.btservice.ProfileService;
-import java.util.HashMap;
-import java.util.Map;
+import bluetooth.constants.AudioInputType;
+import bluetooth.constants.aics.AudioInputStatus;
+import bluetooth.constants.aics.GainMode;
+import bluetooth.constants.aics.Mute;
class VolumeControlInputDescriptor {
- private static final String TAG = "VolumeControlInputDescriptor";
- final Map<Integer, Descriptor> mVolumeInputs = new HashMap<>();
+ private static final String TAG = VolumeControlInputDescriptor.class.getSimpleName();
- public static final int AUDIO_INPUT_TYPE_UNSPECIFIED = 0x00;
- public static final int AUDIO_INPUT_TYPE_BLUETOOTH = 0x01;
- public static final int AUDIO_INPUT_TYPE_MICROPHONE = 0x02;
- public static final int AUDIO_INPUT_TYPE_ANALOG = 0x03;
- public static final int AUDIO_INPUT_TYPE_DIGITAL = 0x04;
- public static final int AUDIO_INPUT_TYPE_RADIO = 0x05;
- public static final int AUDIO_INPUT_TYPE_STREAMING = 0x06;
- public static final int AUDIO_INPUT_TYPE_AMBIENT = 0x07;
+ final Descriptor[] mVolumeInputs;
+
+ VolumeControlInputDescriptor(int numberOfExternalInputs) {
+ mVolumeInputs = new Descriptor[numberOfExternalInputs];
+ // Stack delivers us number of audio inputs. ids are countinous from [0;n[
+ for (int i = 0; i < numberOfExternalInputs; i++) {
+ mVolumeInputs[i] = new Descriptor();
+ }
+ }
private static class Descriptor {
- /* True when input is active, false otherwise */
- boolean mIsActive = false;
+ int mStatus = AudioInputStatus.INACTIVE;
- /* Defined as in Assigned Numbers in the BluetoothVolumeControl.AUDIO_INPUT_TYPE_ */
- int mType = AUDIO_INPUT_TYPE_UNSPECIFIED;
+ int mType = AudioInputType.UNSPECIFIED;
- int mGainValue = 0;
+ int mGainSetting = 0;
- /* As per AICS 1.0
- * 3.1.3. Gain_Mode field
- * The Gain_Mode field shall be set to a value that reflects whether gain modes are
- * manual or automatic.
- *
- * If the Gain_Mode field value is Manual Only, the server allows only manual gain.
- * If the Gain_Mode field is Automatic Only, the server allows only automatic gain.
- *
- * For all other Gain_Mode field values, the server allows switchable
- * automatic/manual gain.
- */
- int mGainMode = 0;
+ int mGainMode = GainMode.MANUAL_ONLY;
- boolean mIsMute = false;
+ int mMute = Mute.DISABLED;
- /* As per AICS 1.0
- * The Gain_Setting (mGainValue) field is a signed value for which a single increment
- * or decrement should result in a corresponding increase or decrease of the input
- * amplitude by the value of the Gain_Setting_Units (mGainSettingsUnits)
- * field of the Gain Setting Properties characteristic value.
+ /* See AICS 1.0
+ * The Gain_Setting (mGainSetting) field is a signed value for which a single increment or
+ * decrement should result in a corresponding increase or decrease of the input amplitude by
+ * the value of the Gain_Setting_Units (mGainSettingsUnits) field of the Gain Setting
+ * Properties characteristic value.
*/
int mGainSettingsUnits = 0;
@@ -76,150 +64,91 @@
}
int size() {
- return mVolumeInputs.size();
+ return mVolumeInputs.length;
}
- void add(int id) {
- if (!mVolumeInputs.containsKey(id)) {
- mVolumeInputs.put(id, new Descriptor());
- }
- }
-
- boolean setActive(int id, boolean active) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "setActive, Id " + id + " is unknown");
+ private boolean isValidId(int id) {
+ if (id >= size() || id < 0) {
+ Log.e(TAG, "Request fail. Illegal id argument: " + id);
return false;
}
- desc.mIsActive = active;
return true;
}
- boolean isActive(int id) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "isActive, Id " + id + " is unknown");
- return false;
- }
- return desc.mIsActive;
+ void setStatus(int id, int status) {
+ if (!isValidId(id)) return;
+ mVolumeInputs[id].mStatus = status;
}
- boolean setDescription(int id, String description) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "setDescription, Id " + id + " is unknown");
- return false;
- }
- desc.mDescription = description;
- return true;
+ int getStatus(int id) {
+ if (!isValidId(id)) return AudioInputStatus.INACTIVE;
+ return mVolumeInputs[id].mStatus;
+ }
+
+ void setDescription(int id, String description) {
+ if (!isValidId(id)) return;
+ mVolumeInputs[id].mDescription = description;
}
String getDescription(int id) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "getDescription, Id " + id + " is unknown");
- return null;
- }
- return desc.mDescription;
+ if (!isValidId(id)) return null;
+ return mVolumeInputs[id].mDescription;
}
- boolean setType(int id, int type) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "setType, Id " + id + " is unknown");
- return false;
- }
-
- if (type > AUDIO_INPUT_TYPE_AMBIENT) {
- Log.e(TAG, "setType, Type " + type + "for id " + id + " is invalid");
- return false;
- }
-
- desc.mType = type;
- return true;
+ void setType(int id, int type) {
+ if (!isValidId(id)) return;
+ mVolumeInputs[id].mType = type;
}
int getType(int id) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "getType, Id " + id + " is unknown");
- return AUDIO_INPUT_TYPE_UNSPECIFIED;
- }
- return desc.mType;
+ if (!isValidId(id)) return AudioInputType.UNSPECIFIED;
+ return mVolumeInputs[id].mType;
}
- int getGain(int id) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "getGain, Id " + id + " is unknown");
- return 0;
- }
- return desc.mGainValue;
+ int getGainSetting(int id) {
+ if (!isValidId(id)) return 0;
+ return mVolumeInputs[id].mGainSetting;
}
- boolean isMuted(int id) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "isMuted, Id " + id + " is unknown");
- return false;
- }
- return desc.mIsMute;
+ int getMute(int id) {
+ if (!isValidId(id)) return Mute.DISABLED;
+ return mVolumeInputs[id].mMute;
}
- boolean setPropSettings(int id, int gainUnit, int gainMin, int gainMax) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "setPropSettings, Id " + id + " is unknown");
- return false;
- }
+ void setPropSettings(int id, int gainUnit, int gainMin, int gainMax) {
+ if (!isValidId(id)) return;
- desc.mGainSettingsUnits = gainUnit;
- desc.mGainSettingsMinSetting = gainMin;
- desc.mGainSettingsMaxSetting = gainMax;
-
- return true;
+ mVolumeInputs[id].mGainSettingsUnits = gainUnit;
+ mVolumeInputs[id].mGainSettingsMinSetting = gainMin;
+ mVolumeInputs[id].mGainSettingsMaxSetting = gainMax;
}
- boolean setState(int id, int gainValue, int gainMode, boolean mute) {
- Descriptor desc = mVolumeInputs.get(id);
- if (desc == null) {
- Log.e(TAG, "Id " + id + " is unknown");
- return false;
+ void setState(int id, int gainSetting, int mute, int gainMode) {
+ if (!isValidId(id)) return;
+
+ Descriptor desc = mVolumeInputs[id];
+
+ if (gainSetting > desc.mGainSettingsMaxSetting
+ || gainSetting < desc.mGainSettingsMinSetting) {
+ Log.e(TAG, "Request fail. Illegal gainSetting argument: " + gainSetting);
+ return;
}
- if (gainValue > desc.mGainSettingsMaxSetting || gainValue < desc.mGainSettingsMinSetting) {
- Log.e(TAG, "Invalid gainValue " + gainValue);
- return false;
- }
-
- desc.mGainValue = gainValue;
+ desc.mGainSetting = gainSetting;
desc.mGainMode = gainMode;
- desc.mIsMute = mute;
-
- return true;
- }
-
- void remove(int id) {
- Log.d(TAG, "remove, id: " + id);
- mVolumeInputs.remove(id);
- }
-
- void clear() {
- Log.d(TAG, "clear all inputs");
- mVolumeInputs.clear();
+ desc.mMute = mute;
}
void dump(StringBuilder sb) {
- for (Map.Entry<Integer, Descriptor> entry : mVolumeInputs.entrySet()) {
- Descriptor desc = entry.getValue();
- Integer id = entry.getKey();
- ProfileService.println(sb, " id: " + id);
+ for (int i = 0; i < mVolumeInputs.length; i++) {
+ Descriptor desc = mVolumeInputs[i];
+ ProfileService.println(sb, " id: " + i);
ProfileService.println(sb, " description: " + desc.mDescription);
ProfileService.println(sb, " type: " + desc.mType);
- ProfileService.println(sb, " isActive: " + desc.mIsActive);
- ProfileService.println(sb, " gainValue: " + desc.mGainValue);
+ ProfileService.println(sb, " status: " + desc.mStatus);
+ ProfileService.println(sb, " gainSetting: " + desc.mGainSetting);
ProfileService.println(sb, " gainMode: " + desc.mGainMode);
- ProfileService.println(sb, " mute: " + desc.mIsMute);
+ ProfileService.println(sb, " mute: " + desc.mMute);
ProfileService.println(sb, " units:" + desc.mGainSettingsUnits);
ProfileService.println(sb, " minGain:" + desc.mGainSettingsMinSetting);
ProfileService.println(sb, " maxGain:" + desc.mGainSettingsMaxSetting);
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java
new file mode 100644
index 0000000..56f4cde
--- /dev/null
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java
@@ -0,0 +1,181 @@
+/*
+ * 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.vc;
+
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED;
+
+import static java.util.Objects.requireNonNull;
+
+import android.bluetooth.BluetoothDevice;
+import android.util.Log;
+
+import com.android.bluetooth.btservice.AdapterService;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Arrays;
+import java.util.function.Consumer;
+
+class VolumeControlNativeCallback {
+ private static final String TAG = VolumeControlNativeCallback.class.getSimpleName();
+
+ private final AdapterService mAdapterService;
+ private final VolumeControlService mVolumeControlService;
+
+ VolumeControlNativeCallback(
+ AdapterService adapterService, VolumeControlService volumeControlService) {
+ mAdapterService = requireNonNull(adapterService);
+ mVolumeControlService = requireNonNull(volumeControlService);
+ }
+
+ private BluetoothDevice getDevice(byte[] address) {
+ return mAdapterService.getDeviceFromByte(address);
+ }
+
+ private void sendMessageToService(Consumer<VolumeControlService> action) {
+ if (!mVolumeControlService.isAvailable()) {
+ StringBuilder sb = new StringBuilder();
+ Arrays.stream(new Throwable().getStackTrace())
+ .skip(1) // skip the inlineStackTrace method in the outputted stack trace
+ .forEach(trace -> sb.append(" [at ").append(trace).append("]"));
+ Log.e(TAG, "Action ignored, service not available: " + sb.toString());
+ return;
+ }
+ action.accept(mVolumeControlService);
+ }
+
+ @VisibleForTesting
+ void onConnectionStateChanged(int state, byte[] address) {
+ VolumeControlStackEvent event =
+ new VolumeControlStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.device = getDevice(address);
+ event.valueInt1 = state;
+
+ Log.d(TAG, "onConnectionStateChanged: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onVolumeStateChanged(
+ int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) {
+ VolumeControlStackEvent event =
+ new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED);
+ event.device = getDevice(address);
+ event.valueInt1 = -1;
+ event.valueInt2 = volume;
+ event.valueInt3 = flags;
+ event.valueBool1 = mute;
+ event.valueBool2 = isAutonomous;
+
+ Log.d(TAG, "onVolumeStateChanged: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) {
+ VolumeControlStackEvent event =
+ new VolumeControlStackEvent(EVENT_TYPE_VOLUME_STATE_CHANGED);
+ event.device = null;
+ event.valueInt1 = groupId;
+ event.valueInt2 = volume;
+ event.valueBool1 = mute;
+ event.valueBool2 = isAutonomous;
+
+ Log.d(TAG, "onGroupVolumeStateChanged: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) {
+ VolumeControlStackEvent event = new VolumeControlStackEvent(EVENT_TYPE_DEVICE_AVAILABLE);
+ event.device = getDevice(address);
+ event.valueInt1 = numOfExternalOutputs;
+ event.valueInt2 = numOfExternalInputs;
+
+ Log.d(TAG, "onDeviceAvailable: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) {
+ VolumeControlStackEvent event =
+ new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED);
+ event.device = getDevice(address);
+ event.valueInt1 = externalOutputId;
+ event.valueInt2 = offset;
+
+ Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) {
+ VolumeControlStackEvent event =
+ new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED);
+ event.device = getDevice(address);
+ event.valueInt1 = externalOutputId;
+ event.valueInt2 = location;
+
+ Log.d(TAG, "onExtAudioOutLocationChanged: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) {
+ VolumeControlStackEvent event =
+ new VolumeControlStackEvent(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED);
+ event.device = getDevice(address);
+ event.valueInt1 = externalOutputId;
+ event.valueString1 = descr;
+
+ Log.d(TAG, "onExtAudioOutLocationChanged: " + event);
+ mVolumeControlService.messageFromNative(event);
+ }
+
+ @VisibleForTesting
+ void onExtAudioInStateChanged(int id, int gainSetting, int gainMode, int mute, byte[] address) {
+ sendMessageToService(
+ s ->
+ s.onExtAudioInStateChanged(
+ getDevice(address), id, gainSetting, mute, gainMode));
+ }
+
+ @VisibleForTesting
+ void onExtAudioInStatusChanged(int id, int status, byte[] address) {
+ sendMessageToService(s -> s.onExtAudioInStatusChanged(getDevice(address), id, status));
+ }
+
+ @VisibleForTesting
+ void onExtAudioInTypeChanged(int id, int type, byte[] address) {
+ sendMessageToService(s -> s.onExtAudioInTypeChanged(getDevice(address), id, type));
+ }
+
+ @VisibleForTesting
+ void onExtAudioInDescriptionChanged(int id, String descr, byte[] address) {
+ sendMessageToService(s -> s.onExtAudioInDescriptionChanged(getDevice(address), id, descr));
+ }
+
+ @VisibleForTesting
+ void onExtAudioInGainPropsChanged(int id, int unit, int min, int max, byte[] address) {
+ sendMessageToService(
+ s -> s.onExtAudioInGainPropsChanged(getDevice(address), id, unit, min, max));
+ }
+}
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java
index 7167293..95db676 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java
@@ -17,327 +17,32 @@
package com.android.bluetooth.vc;
-import android.bluetooth.BluetoothAdapter;
+import static java.util.Objects.requireNonNull;
+
import android.bluetooth.BluetoothDevice;
-import android.util.Log;
import com.android.bluetooth.Utils;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Native;
public class VolumeControlNativeInterface {
- private static final String TAG = "VolumeControlNativeInterface";
- private BluetoothAdapter mAdapter;
+ private static final String TAG = VolumeControlNativeInterface.class.getSimpleName();
- @GuardedBy("INSTANCE_LOCK")
- private static VolumeControlNativeInterface sInstance;
+ // Value access from native, see com_android_bluetooth_vc.cpp
+ @Native private final VolumeControlNativeCallback mNativeCallback;
- private static final Object INSTANCE_LOCK = new Object();
-
- private VolumeControlNativeInterface() {
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mAdapter == null) {
- Log.wtf(TAG, "No Bluetooth Adapter Available");
- }
+ VolumeControlNativeInterface(VolumeControlNativeCallback nativeCallback) {
+ mNativeCallback = requireNonNull(nativeCallback);
}
- /** Get singleton instance. */
- public static VolumeControlNativeInterface getInstance() {
- synchronized (INSTANCE_LOCK) {
- if (sInstance == null) {
- sInstance = new VolumeControlNativeInterface();
- }
- return sInstance;
- }
- }
-
- /** Set singleton instance. */
- @VisibleForTesting
- public static void setInstance(VolumeControlNativeInterface instance) {
- synchronized (INSTANCE_LOCK) {
- sInstance = instance;
- }
- }
-
- /**
- * Initializes the native interface.
- *
- * <p>priorities to configure.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void init() {
+ void init() {
initNative();
}
- /** Cleanup the native interface. */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void cleanup() {
+ void cleanup() {
cleanupNative();
}
- /**
- * Initiates VolumeControl connection to a remote device.
- *
- * @param device the remote device
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean connectVolumeControl(BluetoothDevice device) {
- return connectVolumeControlNative(getByteAddress(device));
- }
-
- /**
- * Disconnects VolumeControl from a remote device.
- *
- * @param device the remote device
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean disconnectVolumeControl(BluetoothDevice device) {
- return disconnectVolumeControlNative(getByteAddress(device));
- }
-
- /** Sets the VolumeControl volume */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void setVolume(BluetoothDevice device, int volume) {
- setVolumeNative(getByteAddress(device), volume);
- }
-
- /** Sets the VolumeControl volume for the group */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void setGroupVolume(int groupId, int volume) {
- setGroupVolumeNative(groupId, volume);
- }
-
- /** Mute the VolumeControl volume */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void mute(BluetoothDevice device) {
- muteNative(getByteAddress(device));
- }
-
- /** Mute the VolumeControl volume in the group */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void muteGroup(int groupId) {
- muteGroupNative(groupId);
- }
-
- /** Unmute the VolumeControl volume */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void unmute(BluetoothDevice device) {
- unmuteNative(getByteAddress(device));
- }
-
- /** Unmute the VolumeControl volume group */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public void unmuteGroup(int groupId) {
- unmuteGroupNative(groupId);
- }
-
- /**
- * Gets external audio output volume offset from a remote device.
- *
- * @param device the remote device
- * @param externalOutputId external audio output id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId) {
- return getExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId);
- }
-
- /**
- * Sets external audio output volume offset to a remote device.
- *
- * @param device the remote device
- * @param externalOutputId external audio output id
- * @param offset requested offset
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioOutVolumeOffset(
- BluetoothDevice device, int externalOutputId, int offset) {
- if (Utils.isPtsTestMode()) {
- setVolumeNative(getByteAddress(device), offset);
- return true;
- }
- return setExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId, offset);
- }
-
- /**
- * Gets external audio output location from a remote device.
- *
- * @param device the remote device
- * @param externalOutputId external audio output id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioOutLocation(BluetoothDevice device, int externalOutputId) {
- return getExtAudioOutLocationNative(getByteAddress(device), externalOutputId);
- }
-
- /**
- * Sets external audio volume offset to a remote device.
- *
- * @param device the remote device
- * @param externalOutputId external audio output id
- * @param location requested location
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioOutLocation(
- BluetoothDevice device, int externalOutputId, int location) {
- return setExtAudioOutLocationNative(getByteAddress(device), externalOutputId, location);
- }
-
- /**
- * Gets external audio output description from a remote device.
- *
- * @param device the remote device
- * @param externalOutputId external audio output id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioOutDescription(BluetoothDevice device, int externalOutputId) {
- return getExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId);
- }
-
- /**
- * Sets external audio volume description to a remote device.
- *
- * @param device the remote device
- * @param externalOutputId external audio output id
- * @param descr requested description
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioOutDescription(
- BluetoothDevice device, int externalOutputId, String descr) {
- return setExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId, descr);
- }
-
- /**
- * Gets external audio input state from a remote device.
- *
- * <p>note: state describes configuration
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioInState(BluetoothDevice device, int externalInputId) {
- return getExtAudioInStateNative(getByteAddress(device), externalInputId);
- }
-
- /**
- * Gets external audio input status from a remote device.
- *
- * <p>note: status says if input is active or not.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioInStatus(BluetoothDevice device, int externalInputId) {
- return getExtAudioInStatusNative(getByteAddress(device), externalInputId);
- }
-
- /**
- * Gets external audio input type from a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioInType(BluetoothDevice device, int externalInputId) {
- return getExtAudioInTypeNative(getByteAddress(device), externalInputId);
- }
-
- /**
- * Gets external audio input gain properties from a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioInGainProps(BluetoothDevice device, int externalInputId) {
- return getExtAudioInGainPropsNative(getByteAddress(device), externalInputId);
- }
-
- /**
- * Gets external audio input description from a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean getExtAudioInDescription(BluetoothDevice device, int externalInputId) {
- return getExtAudioInDescriptionNative(getByteAddress(device), externalInputId);
- }
-
- /**
- * Sets external audio input description from a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @param descr requested description
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioInDescription(
- BluetoothDevice device, int externalInputId, String descr) {
- return setExtAudioInDescriptionNative(getByteAddress(device), externalInputId, descr);
- }
-
- /**
- * Sets external audio input gain value to a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @param value requested gain value
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioInGainValue(BluetoothDevice device, int externalInputId, int value) {
- return setExtAudioInGainValueNative(getByteAddress(device), externalInputId, value);
- }
-
- /**
- * Sets external audio input gain mode to a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @param autoMode true when auto mode requested
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioInGainMode(
- BluetoothDevice device, int externalInputId, boolean autoMode) {
- return setExtAudioInGainModeNative(getByteAddress(device), externalInputId, autoMode);
- }
-
- /**
- * Sets external audio input gain mode to a remote device.
- *
- * @param device the remote device
- * @param externalInputId external audio input id
- * @param mute true when mute requested
- * @return true on success, otherwise false.
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean setExtAudioInGainMute(
- BluetoothDevice device, int externalInputId, boolean mute) {
- return setExtAudioInGainMuteNative(getByteAddress(device), externalInputId, mute);
- }
-
- private BluetoothDevice getDevice(byte[] address) {
- return mAdapter.getRemoteDevice(address);
- }
-
private byte[] getByteAddress(BluetoothDevice device) {
if (device == null) {
return Utils.getBytesFromAddress("00:00:00:00:00:00");
@@ -345,182 +50,100 @@
return Utils.getBytesFromAddress(device.getAddress());
}
- private void sendMessageToService(VolumeControlStackEvent event) {
- VolumeControlService service = VolumeControlService.getVolumeControlService();
- if (service != null) {
- service.messageFromNative(event);
- } else {
- Log.e(TAG, "Event ignored, service not available: " + event);
+ boolean connectVolumeControl(BluetoothDevice device) {
+ return connectVolumeControlNative(getByteAddress(device));
+ }
+
+ boolean disconnectVolumeControl(BluetoothDevice device) {
+ return disconnectVolumeControlNative(getByteAddress(device));
+ }
+
+ void setVolume(BluetoothDevice device, int volume) {
+ setVolumeNative(getByteAddress(device), volume);
+ }
+
+ void setGroupVolume(int groupId, int volume) {
+ setGroupVolumeNative(groupId, volume);
+ }
+
+ void mute(BluetoothDevice device) {
+ muteNative(getByteAddress(device));
+ }
+
+ void muteGroup(int groupId) {
+ muteGroupNative(groupId);
+ }
+
+ void unmute(BluetoothDevice device) {
+ unmuteNative(getByteAddress(device));
+ }
+
+ void unmuteGroup(int groupId) {
+ unmuteGroupNative(groupId);
+ }
+
+ boolean getExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId) {
+ return getExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId);
+ }
+
+ boolean setExtAudioOutVolumeOffset(BluetoothDevice device, int externalOutputId, int offset) {
+ if (Utils.isPtsTestMode()) {
+ setVolumeNative(getByteAddress(device), offset);
+ return true;
}
+ return setExtAudioOutVolumeOffsetNative(getByteAddress(device), externalOutputId, offset);
}
- // Callbacks from the native stack back into the Java framework.
- // All callbacks are routed via the Service which will disambiguate which
- // state machine the message should be routed to.
- @VisibleForTesting
- void onConnectionStateChanged(int state, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = state;
-
- Log.d(TAG, "onConnectionStateChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioOutLocation(BluetoothDevice device, int externalOutputId) {
+ return getExtAudioOutLocationNative(getByteAddress(device), externalOutputId);
}
- @VisibleForTesting
- void onVolumeStateChanged(
- int volume, boolean mute, int flags, byte[] address, boolean isAutonomous) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = -1;
- event.valueInt2 = volume;
- event.valueInt3 = flags;
- event.valueBool1 = mute;
- event.valueBool2 = isAutonomous;
-
- Log.d(TAG, "onVolumeStateChanged: " + event);
- sendMessageToService(event);
+ boolean setExtAudioOutLocation(BluetoothDevice device, int externalOutputId, int location) {
+ return setExtAudioOutLocationNative(getByteAddress(device), externalOutputId, location);
}
- @VisibleForTesting
- void onGroupVolumeStateChanged(int volume, boolean mute, int groupId, boolean isAutonomous) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
- event.device = null;
- event.valueInt1 = groupId;
- event.valueInt2 = volume;
- event.valueBool1 = mute;
- event.valueBool2 = isAutonomous;
-
- Log.d(TAG, "onGroupVolumeStateChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioOutDescription(BluetoothDevice device, int externalOutputId) {
+ return getExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId);
}
- @VisibleForTesting
- void onDeviceAvailable(int numOfExternalOutputs, int numOfExternalInputs, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
- event.device = getDevice(address);
- event.valueInt1 = numOfExternalOutputs;
- event.valueInt2 = numOfExternalInputs;
-
- Log.d(TAG, "onDeviceAvailable: " + event);
- sendMessageToService(event);
+ boolean setExtAudioOutDescription(BluetoothDevice device, int externalOutputId, String descr) {
+ return setExtAudioOutDescriptionNative(getByteAddress(device), externalOutputId, descr);
}
- @VisibleForTesting
- void onExtAudioOutVolumeOffsetChanged(int externalOutputId, int offset, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalOutputId;
- event.valueInt2 = offset;
-
- Log.d(TAG, "onExtAudioOutVolumeOffsetChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioInState(BluetoothDevice device, int externalInputId) {
+ return getExtAudioInStateNative(getByteAddress(device), externalInputId);
}
- @VisibleForTesting
- void onExtAudioOutLocationChanged(int externalOutputId, int location, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalOutputId;
- event.valueInt2 = location;
-
- Log.d(TAG, "onExtAudioOutLocationChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioInStatus(BluetoothDevice device, int externalInputId) {
+ return getExtAudioInStatusNative(getByteAddress(device), externalInputId);
}
- @VisibleForTesting
- void onExtAudioOutDescriptionChanged(int externalOutputId, String descr, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalOutputId;
- event.valueString1 = descr;
-
- Log.d(TAG, "onExtAudioOutLocationChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioInType(BluetoothDevice device, int externalInputId) {
+ return getExtAudioInTypeNative(getByteAddress(device), externalInputId);
}
- @VisibleForTesting
- void onExtAudioInStateChanged(
- int externalInputId, int gainValue, int gainMode, boolean mute, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalInputId;
- event.valueInt2 = gainValue;
- event.valueInt3 = gainMode;
- event.valueBool1 = mute;
-
- Log.d(TAG, "onExtAudioInStateChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioInGainProps(BluetoothDevice device, int externalInputId) {
+ return getExtAudioInGainPropsNative(getByteAddress(device), externalInputId);
}
- @VisibleForTesting
- void onExtAudioInStatusChanged(int externalInputId, int status, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalInputId;
- event.valueInt2 = status;
-
- Log.d(TAG, "onExtAudioInStatusChanged: " + event);
- sendMessageToService(event);
+ boolean getExtAudioInDescription(BluetoothDevice device, int externalInputId) {
+ return getExtAudioInDescriptionNative(getByteAddress(device), externalInputId);
}
- @VisibleForTesting
- void onExtAudioInTypeChanged(int externalInputId, int type, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalInputId;
- event.valueInt2 = type;
-
- Log.d(TAG, "onExtAudioInTypeChanged: " + event);
- sendMessageToService(event);
+ boolean setExtAudioInDescription(BluetoothDevice device, int externalInputId, String descr) {
+ return setExtAudioInDescriptionNative(getByteAddress(device), externalInputId, descr);
}
- @VisibleForTesting
- void onExtAudioInDescriptionChanged(int externalInputId, String descr, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalInputId;
- event.valueString1 = descr;
-
- Log.d(TAG, "onExtAudioInDescriptionChanged: " + event);
- sendMessageToService(event);
+ boolean setExtAudioInGainSetting(BluetoothDevice device, int externalInputId, int gainSetting) {
+ return setExtAudioInGainSettingNative(getByteAddress(device), externalInputId, gainSetting);
}
- @VisibleForTesting
- void onExtAudioInGainPropsChanged(
- int externalInputId, int unit, int min, int max, byte[] address) {
- VolumeControlStackEvent event =
- new VolumeControlStackEvent(
- VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED);
- event.device = getDevice(address);
- event.valueInt1 = externalInputId;
- event.valueInt2 = unit;
- event.valueInt3 = min;
- event.valueInt4 = max;
+ boolean setExtAudioInGainMode(BluetoothDevice device, int externalInputId, boolean autoMode) {
+ return setExtAudioInGainModeNative(getByteAddress(device), externalInputId, autoMode);
+ }
- Log.d(TAG, "onExtAudioInGainPropsChanged: " + event);
- sendMessageToService(event);
+ boolean setExtAudioInGainMute(BluetoothDevice device, int externalInputId, boolean mute) {
+ return setExtAudioInGainMuteNative(getByteAddress(device), externalInputId, mute);
}
// Native methods that call into the JNI interface
@@ -573,8 +196,8 @@
private native boolean setExtAudioInDescriptionNative(
byte[] address, int externalInputId, String descr);
- private native boolean setExtAudioInGainValueNative(
- byte[] address, int externalInputId, int gainValue);
+ private native boolean setExtAudioInGainSettingNative(
+ byte[] address, int externalInputId, int gainSetting);
private native boolean setExtAudioInGainModeNative(
byte[] address, int externalInputId, boolean modeAuto);
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
index 99f296b..23c287b 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlService.java
@@ -29,6 +29,7 @@
import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
import static java.util.Objects.requireNonNull;
+import static java.util.Objects.requireNonNullElseGet;
import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
@@ -63,6 +64,9 @@
import libcore.util.SneakyThrow;
+import bluetooth.constants.AudioInputType;
+import bluetooth.constants.aics.AudioInputStatus;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -111,7 +115,7 @@
@VisibleForTesting ServiceFactory mFactory = new ServiceFactory();
public VolumeControlService(AdapterService adapterService) {
- this(adapterService, null, VolumeControlNativeInterface.getInstance());
+ this(adapterService, null, null);
}
@VisibleForTesting
@@ -122,7 +126,12 @@
super(requireNonNull(adapterService));
mAdapterService = adapterService;
mDatabaseManager = requireNonNull(mAdapterService.getDatabase());
- mNativeInterface = requireNonNull(nativeInterface);
+ mNativeInterface =
+ requireNonNullElseGet(
+ nativeInterface,
+ () ->
+ new VolumeControlNativeInterface(
+ new VolumeControlNativeCallback(adapterService, this)));
mAudioManager = requireNonNull(getSystemService(AudioManager.class));
if (looper == null) {
mHandler = new Handler(requireNonNull(Looper.getMainLooper()));
@@ -935,23 +944,11 @@
void handleExternalInputs(BluetoothDevice device, int numberOfExternalInputs) {
if (numberOfExternalInputs == 0) {
Log.i(TAG, "Volume offset not available");
+ mAudioInputs.remove(device);
return;
}
- VolumeControlInputDescriptor inputs = mAudioInputs.get(device);
- if (inputs == null) {
- inputs = new VolumeControlInputDescriptor();
- mAudioInputs.put(device, inputs);
- } else if (inputs.size() != numberOfExternalInputs) {
- Log.i(TAG, "Number of inputs changed: ");
- inputs.clear();
- }
-
- /* Stack delivers us number of audio inputs.
- * Offset ids a countinous from 1 to numberOfExternalInputs*/
- for (int i = 1; i <= numberOfExternalInputs; i++) {
- inputs.add(i);
- }
+ mAudioInputs.put(device, new VolumeControlInputDescriptor(numberOfExternalInputs));
}
void handleDeviceAvailable(
@@ -1033,138 +1030,119 @@
}
}
- void handleDeviceExtInputStateChanged(
- BluetoothDevice device, int id, int gainValue, int gainMode, boolean mute) {
- Log.d(
- TAG,
- ("handleDeviceExtInputStateChanged, device: " + device)
- + (" inputId: " + id)
- + (" gainValue: " + gainValue)
+ void onExtAudioInStateChanged(
+ BluetoothDevice device, int id, int gainSetting, int mute, int gainMode) {
+ String logInfo =
+ "onExtAudioInStateChanged("
+ + ("device:" + device)
+ + (", id" + id)
+ + (" gainSetting: " + gainSetting)
+ (" gainMode: " + gainMode)
- + (" mute: " + mute));
+ + (" mute: " + mute)
+ + ")";
VolumeControlInputDescriptor input = mAudioInputs.get(device);
if (input == null) {
- Log.e(
- TAG,
- ("handleDeviceExtInputStateChanged, inputId: " + id)
- + (" not found for device: " + device));
+ Log.e(TAG, logInfo + " This device has no audio input control");
return;
}
- if (!input.setState(id, gainValue, gainMode, mute)) {
- Log.e(
- TAG,
- ("handleDeviceExtInputStateChanged, error while setting inputId: " + id)
- + ("for: " + device));
- }
+
+ Log.d(TAG, logInfo);
+ input.setState(id, gainSetting, mute, gainMode);
}
- void handleDeviceExtInputStatusChanged(BluetoothDevice device, int id, int status) {
- Log.d(TAG, " device: " + device + " inputId: " + id + " status: " + status);
+ void onExtAudioInStatusChanged(BluetoothDevice device, int id, int status) {
+ String logInfo =
+ "onExtAudioInStatusChanged("
+ + ("device:" + device)
+ + (", id" + id)
+ + (", status" + status)
+ + ")";
VolumeControlInputDescriptor input = mAudioInputs.get(device);
if (input == null) {
- Log.e(TAG, " inputId: " + id + " not found for device: " + device);
+ Log.e(TAG, logInfo + " This device has no audio input control");
return;
}
- /*
- * As per ACIS 1.0. Status
- * Inactive: 0x00
- * Active: 0x01
- */
- if (status > 1 || status < 0) {
- Log.e(
- TAG,
- ("handleDeviceExtInputStatusChanged, invalid status: " + status)
- + (" for: " + device));
+ if (status != AudioInputStatus.INACTIVE && status != AudioInputStatus.ACTIVE) {
+ Log.e(TAG, logInfo + ": Invalid status argument");
return;
}
- boolean active = (status == 0x01);
- if (!input.setActive(id, active)) {
- Log.e(
- TAG,
- ("handleDeviceExtInputStatusChanged, error while setting inputId: " + id)
- + ("for: " + device));
- }
+ Log.d(TAG, logInfo);
+ input.setStatus(id, status);
}
- void handleDeviceExtInputTypeChanged(BluetoothDevice device, int id, int type) {
- Log.d(
- TAG,
- ("handleDeviceExtInputTypeChanged, device: " + device)
- + (" inputId: " + id)
- + (" type: " + type));
+ void onExtAudioInTypeChanged(BluetoothDevice device, int id, int type) {
+ String logInfo =
+ "onExtAudioInTypeChanged("
+ + ("device:" + device)
+ + (", id" + id)
+ + (", type" + type)
+ + ")";
VolumeControlInputDescriptor input = mAudioInputs.get(device);
if (input == null) {
- Log.e(
- TAG,
- ("handleDeviceExtInputTypeChanged, inputId: " + id)
- + (" not found for device: " + device));
+ Log.e(TAG, logInfo + ": This device has no audio input control");
return;
}
- if (!input.setType(id, type)) {
- Log.e(
- TAG,
- ("handleDeviceExtInputTypeChanged, error while setting inputId: " + id)
- + ("for: " + device));
+ if (type > AudioInputType.AMBIENT) {
+ Log.e(TAG, logInfo + ": Invalid type argument");
+ return;
}
+
+ Log.d(TAG, logInfo);
+ input.setType(id, type);
}
- void handleDeviceExtInputDescriptionChanged(
- BluetoothDevice device, int id, String description) {
- Log.d(
- TAG,
- ("handleDeviceExtInputDescriptionChanged, device: " + device)
- + (" inputId: " + id)
- + (" description: " + description));
+ void onExtAudioInDescriptionChanged(BluetoothDevice device, int id, String description) {
+ String logInfo =
+ "onExtAudioInDescriptionChanged("
+ + ("device:" + device)
+ + (", id" + id)
+ + (", description" + description)
+ + ")";
VolumeControlInputDescriptor input = mAudioInputs.get(device);
if (input == null) {
- Log.e(
- TAG,
- ("handleDeviceExtInputDescriptionChanged, inputId: " + id)
- + (" not found for device: " + device));
+ Log.e(TAG, logInfo + ": This device has no audio input control");
return;
}
- if (!input.setDescription(id, description)) {
- Log.e(
- TAG,
- ("handleDeviceExtInputDescriptionChanged, error while setting inputId: " + id)
- + ("for: " + device));
+ if (description == null) {
+ Log.e(TAG, logInfo + ": Invalid description argument");
+ return;
}
+
+ Log.d(TAG, logInfo);
+ input.setDescription(id, description);
}
- void handleDeviceExtInputGainPropsChanged(
- BluetoothDevice device, int id, int unit, int min, int max) {
- Log.d(
- TAG,
- ("handleDeviceExtInputGainPropsChanged, device: " + device)
- + (" inputId: " + id)
- + (" unit: " + unit + " min" + min + " max:" + max));
+ void onExtAudioInGainPropsChanged(BluetoothDevice device, int id, int unit, int min, int max) {
+ String logInfo =
+ "onExtAudioInGainPropsChanged("
+ + ("device:" + device)
+ + (", id" + id)
+ + (" unit: " + unit + " min" + min + " max:" + max)
+ + ")";
VolumeControlInputDescriptor input = mAudioInputs.get(device);
if (input == null) {
- Log.e(
- TAG,
- ("handleDeviceExtInputGainPropsChanged, inputId: " + id)
- + (" not found for device: " + device));
+ Log.e(TAG, logInfo + ": This device has no audio input control");
return;
}
- if (!input.setPropSettings(id, unit, min, max)) {
- Log.e(
- TAG,
- ("handleDeviceExtInputGainPropsChanged, error while setting inputId: " + id)
- + ("for: " + device));
- }
+ Log.d(TAG, logInfo);
+ input.setPropSettings(id, unit, min, max);
}
void messageFromNative(VolumeControlStackEvent stackEvent) {
+ if (!isAvailable()) {
+ Log.e(TAG, "Event ignored, service not available: " + stackEvent);
+ return;
+ }
Log.d(TAG, "messageFromNative: " + stackEvent);
if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED) {
@@ -1204,42 +1182,6 @@
return;
}
- if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED) {
- handleDeviceExtInputStateChanged(
- device,
- stackEvent.valueInt1,
- stackEvent.valueInt2,
- stackEvent.valueInt3,
- stackEvent.valueBool1);
- return;
- }
-
- if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED) {
- handleDeviceExtInputStatusChanged(device, stackEvent.valueInt1, stackEvent.valueInt2);
- return;
- }
-
- if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED) {
- handleDeviceExtInputTypeChanged(device, stackEvent.valueInt1, stackEvent.valueInt2);
- return;
- }
-
- if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED) {
- handleDeviceExtInputDescriptionChanged(
- device, stackEvent.valueInt1, stackEvent.valueString1);
- return;
- }
-
- if (stackEvent.type == VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED) {
- handleDeviceExtInputGainPropsChanged(
- device,
- stackEvent.valueInt1,
- stackEvent.valueInt2,
- stackEvent.valueInt3,
- stackEvent.valueInt4);
- return;
- }
-
synchronized (mStateMachines) {
VolumeControlStateMachine sm = mStateMachines.get(device);
if (sm == null) {
diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java
index d102952..b1f2840 100644
--- a/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java
+++ b/android/app/src/com/android/bluetooth/vc/VolumeControlStackEvent.java
@@ -29,18 +29,12 @@
public static final int EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED = 4;
public static final int EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED = 5;
public static final int EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED = 6;
- public static final int EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED = 7;
- public static final int EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED = 8;
- public static final int EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED = 9;
- public static final int EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED = 10;
- public static final int EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED = 11;
public int type;
public BluetoothDevice device;
public int valueInt1;
public int valueInt2;
public int valueInt3;
- public int valueInt4;
public boolean valueBool1;
public boolean valueBool2;
public String valueString1;
@@ -60,7 +54,6 @@
result.append(", valueInt1:").append(eventTypeValue1ToString(type, valueInt1));
result.append(", valueInt2:").append(eventTypeValue2ToString(type, valueInt2));
result.append(", valueInt3:").append(eventTypeValue3ToString(type, valueInt3));
- result.append(", valueInt4:").append(eventTypeValue4ToString(type, valueInt4));
result.append(", valueBool1:").append(eventTypeValueBool1ToString(type, valueBool1));
result.append(", valueBool2:").append(eventTypeValueBool2ToString(type, valueBool2));
result.append(", valueString1:").append(eventTypeString1ToString(type, valueString1));
@@ -84,16 +77,6 @@
return "EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED";
case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED:
return "EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED";
- case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
- return "EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED";
- case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED:
- return "EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED";
- case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED:
- return "EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED";
- case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED:
- return "EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED";
- case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED:
- return "EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED";
default:
return "EVENT_TYPE_UNKNOWN:" + type;
}
@@ -111,12 +94,6 @@
case EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED:
case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED:
return "{ext output id:" + value + "}";
- case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
- case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED:
- case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED:
- case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED:
- case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED:
- return "{ext input id:" + value + "}";
default:
break;
}
@@ -131,12 +108,6 @@
return "{volume:" + value + "}";
case EVENT_TYPE_DEVICE_AVAILABLE:
return "{num_ext_inputs:" + value + "}";
- case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
- return "{ext gain val:" + value + "}";
- case EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED:
- return "{status:" + value + "}";
- case EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED:
- return "{type:" + value + "}";
default:
break;
}
@@ -145,8 +116,6 @@
private static String eventTypeValue3ToString(int type, int value) {
switch (type) {
- case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
- return "{ext gain mode:" + value + "}";
case EVENT_TYPE_VOLUME_STATE_CHANGED:
return "{flags:" + value + "}";
default:
@@ -155,20 +124,9 @@
return Integer.toString(value);
}
- private static String eventTypeValue4ToString(int type, int value) {
- switch (type) {
- case EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED:
- return "{gain set max:" + value + "}";
- default:
- break;
- }
- return Integer.toString(value);
- }
-
private static String eventTypeValueBool1ToString(int type, boolean value) {
switch (type) {
case EVENT_TYPE_VOLUME_STATE_CHANGED:
- case EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED:
return "{muted:" + value + "}";
default:
break;
@@ -189,7 +147,6 @@
private static String eventTypeString1ToString(int type, String value) {
switch (type) {
case EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED:
- case EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED:
return "{description:" + value + "}";
default:
break;
diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java
index 2503b16..97a0aac 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java
@@ -15,6 +15,12 @@
*/
package com.android.bluetooth.a2dpsink;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
+import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
@@ -26,11 +32,10 @@
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioFormat;
+import android.media.AudioManager;
import android.os.test.TestLooper;
-import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
-import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
@@ -52,69 +57,44 @@
@MediumTest
@RunWith(AndroidJUnit4.class)
public class A2dpSinkServiceTest {
- private A2dpSinkService mService = null;
- private BluetoothAdapter mAdapter = null;
- private Context mTargetContext;
-
- @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
-
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock private AdapterService mAdapterService;
@Mock private DatabaseManager mDatabaseManager;
@Mock private A2dpSinkNativeInterface mNativeInterface;
- private BluetoothDevice mDevice1;
- private BluetoothDevice mDevice2;
- private BluetoothDevice mDevice3;
- private BluetoothDevice mDevice4;
- private BluetoothDevice mDevice5;
- private BluetoothDevice mDevice6;
-
- private TestLooper mLooper;
-
private static final int TEST_SAMPLE_RATE = 44;
private static final int TEST_CHANNEL_COUNT = 1;
+ private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+ private final BluetoothDevice mDevice1 = mAdapter.getRemoteDevice("11:11:11:11:11:11");
+ private final BluetoothDevice mDevice2 = mAdapter.getRemoteDevice("22:22:22:22:22:22");
+
+ private TestLooper mLooper;
+ private A2dpSinkService mService;
+
@Before
public void setUp() throws Exception {
- mTargetContext = InstrumentationRegistry.getTargetContext();
-
- mLooper = new TestLooper();
-
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- assertThat(mAdapter).isNotNull();
- mDevice1 = mAdapter.getRemoteDevice("11:11:11:11:11:11");
- mDevice2 = mAdapter.getRemoteDevice("22:22:22:22:22:22");
- mDevice3 = mAdapter.getRemoteDevice("33:33:33:33:33:33");
- mDevice4 = mAdapter.getRemoteDevice("44:44:44:44:44:44");
- mDevice5 = mAdapter.getRemoteDevice("55:55:55:55:55:55");
- mDevice6 = mAdapter.getRemoteDevice("66:66:66:66:66:66");
- BluetoothDevice[] bondedDevices =
- new BluetoothDevice[] {mDevice1, mDevice2, mDevice3, mDevice4, mDevice5, mDevice6};
-
- doReturn(true).when(mDatabaseManager).setProfileConnectionPolicy(any(), anyInt(), anyInt());
+ BluetoothDevice[] bondedDevices = new BluetoothDevice[] {mDevice1, mDevice2};
doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
doReturn(bondedDevices).when(mAdapterService).getBondedDevices();
doReturn(1).when(mAdapterService).getMaxConnectedAudioDevices();
+ TestUtils.mockGetSystemService(mAdapterService, Context.AUDIO_SERVICE, AudioManager.class);
- TestUtils.setAdapterService(mAdapterService);
+ doReturn(true).when(mDatabaseManager).setProfileConnectionPolicy(any(), anyInt(), anyInt());
doReturn(true).when(mNativeInterface).setActiveDevice(any());
- mService = new A2dpSinkService(mTargetContext, mNativeInterface, mLooper.getLooper());
- mService.start();
- assertThat(mLooper.nextMessage()).isNull();
+ mLooper = new TestLooper();
+
+ mService = new A2dpSinkService(mAdapterService, mNativeInterface, mLooper.getLooper());
}
@After
public void tearDown() throws Exception {
- assertThat(mLooper.nextMessage()).isNull();
-
mService.stop();
assertThat(A2dpSinkService.getA2dpSinkService()).isNull();
- TestUtils.clearAdapterService(mAdapterService);
}
private void syncHandler(int... what) {
@@ -123,17 +103,15 @@
private void setupDeviceConnection(BluetoothDevice device) {
assertThat(mLooper.nextMessage()).isNull();
- assertThat(mService.getConnectionState(device))
- .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mService.getConnectionState(device)).isEqualTo(STATE_DISCONNECTED);
assertThat(mLooper.nextMessage()).isNull();
assertThat(mService.connect(device)).isTrue();
- syncHandler(-2 /* SM_INIT_CMD */, A2dpSinkStateMachine.CONNECT);
- StackEvent nativeEvent =
- StackEvent.connectionStateChanged(device, StackEvent.CONNECTION_STATE_CONNECTED);
+ syncHandler(-2 /* SM_INIT_CMD */, A2dpSinkStateMachine.MESSAGE_CONNECT);
+ StackEvent nativeEvent = StackEvent.connectionStateChanged(device, STATE_CONNECTED);
mService.messageFromNative(nativeEvent);
- syncHandler(A2dpSinkStateMachine.STACK_EVENT);
- assertThat(mService.getConnectionState(device)).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT);
+ assertThat(mService.getConnectionState(device)).isEqualTo(STATE_CONNECTED);
}
/**
@@ -143,43 +121,48 @@
* @param priority - The priority value you want the device to have
*/
private void mockDevicePriority(BluetoothDevice device, int priority) {
- when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.A2DP_SINK))
- .thenReturn(priority);
+ doReturn(priority)
+ .when(mDatabaseManager)
+ .getProfileConnectionPolicy(device, BluetoothProfile.A2DP_SINK);
}
/** Test that initialization of the service completes and that we can get a instance */
@Test
public void testInitialize() {
assertThat(A2dpSinkService.getA2dpSinkService()).isEqualTo(mService);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that asking to connect with a null device fails */
@Test
public void testConnectNullDevice() {
assertThrows(IllegalArgumentException.class, () -> mService.connect(null));
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that a CONNECTION_POLICY_ALLOWED device can connected */
@Test
public void testConnectPolicyAllowedDevice() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that a CONNECTION_POLICY_FORBIDDEN device is not allowed to connect */
@Test
public void testConnectPolicyForbiddenDevice() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_FORBIDDEN);
assertThat(mService.connect(mDevice1)).isFalse();
- assertThat(mService.getConnectionState(mDevice1))
- .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that a CONNECTION_POLICY_UNKNOWN device is allowed to connect */
@Test
public void testConnectPolicyUnknownDevice() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_UNKNOWN);
setupDeviceConnection(mDevice1);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that we can connect multiple devices */
@@ -187,44 +170,40 @@
public void testConnectMultipleDevices() {
doReturn(5).when(mAdapterService).getMaxConnectedAudioDevices();
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- mockDevicePriority(mDevice2, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- mockDevicePriority(mDevice3, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- mockDevicePriority(mDevice4, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- mockDevicePriority(mDevice5, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- mockDevicePriority(mDevice6, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice2, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
setupDeviceConnection(mDevice2);
- setupDeviceConnection(mDevice3);
- setupDeviceConnection(mDevice4);
- setupDeviceConnection(mDevice5);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test to make sure we can disconnect a connected device */
@Test
public void testDisconnect() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
assertThat(mService.disconnect(mDevice1)).isTrue();
- syncHandler(A2dpSinkStateMachine.DISCONNECT);
- assertThat(mService.getConnectionState(mDevice1))
- .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT);
+ assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Assure disconnect() fails with a device that's not connected */
@Test
public void testDisconnectDeviceDoesNotExist() {
assertThat(mService.disconnect(mDevice1)).isFalse();
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Assure disconnect() fails with an invalid device */
@Test
public void testDisconnectNullDevice() {
assertThrows(IllegalArgumentException.class, () -> mService.disconnect(null));
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Assure dump() returns something and does not crash */
@@ -233,6 +212,7 @@
StringBuilder sb = new StringBuilder();
mService.dump(sb);
assertThat(sb.toString()).isNotNull();
+ assertThat(mLooper.nextMessage()).isNull();
}
/**
@@ -241,10 +221,11 @@
*/
@Test
public void testSetActiveDevice() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
assertThat(mService.getActiveDevice()).isNotEqualTo(mDevice1);
assertThat(mService.setActiveDevice(mDevice1)).isTrue();
assertThat(mService.getActiveDevice()).isEqualTo(mDevice1);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that calls to set a null active device succeed in unsetting the active device */
@@ -252,24 +233,26 @@
public void testSetActiveDeviceNullDevice() {
assertThat(mService.setActiveDevice(null)).isTrue();
assertThat(mService.getActiveDevice()).isNull();
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Make sure we can receive the set audio configuration */
@Test
public void testGetAudioConfiguration() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
StackEvent audioConfigChanged =
StackEvent.audioConfigChanged(mDevice1, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT);
mService.messageFromNative(audioConfigChanged);
- syncHandler(A2dpSinkStateMachine.STACK_EVENT);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT);
BluetoothAudioConfig expected =
new BluetoothAudioConfig(
TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT, AudioFormat.ENCODING_PCM_16BIT);
BluetoothAudioConfig config = mService.getAudioConfig(mDevice1);
assertThat(config).isEqualTo(expected);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Make sure we ignore audio configuration changes for disconnected/unknown devices */
@@ -279,31 +262,34 @@
StackEvent.audioConfigChanged(null, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT);
mService.messageFromNative(audioConfigChanged);
assertThat(mService.getAudioConfig(null)).isNull();
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Make sure we ignore audio configuration changes for disconnected/unknown devices */
@Test
public void testOnAudioConfigChanged_withUnknownDevice_eventDropped() {
- assertThat(mService.getConnectionState(mDevice1))
- .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED);
StackEvent audioConfigChanged =
StackEvent.audioConfigChanged(mDevice1, TEST_SAMPLE_RATE, TEST_CHANNEL_COUNT);
mService.messageFromNative(audioConfigChanged);
assertThat(mService.getAudioConfig(mDevice1)).isNull();
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Getting an audio config for a device that hasn't received one yet should return null */
@Test
public void testGetAudioConfigWithConfigUnset() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
assertThat(mService.getAudioConfig(mDevice1)).isNull();
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Getting an audio config for a null device should return null */
@Test
public void testGetAudioConfigNullDevice() {
assertThat(mService.getAudioConfig(null)).isNull();
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that a newly connected device ends up in the set returned by getConnectedDevices */
@@ -312,11 +298,12 @@
ArrayList<BluetoothDevice> expected = new ArrayList<BluetoothDevice>();
expected.add(mDevice1);
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
List<BluetoothDevice> devices = mService.getConnectedDevices();
assertThat(devices).isEqualTo(expected);
+ assertThat(mLooper.nextMessage()).isNull();
}
/**
@@ -327,13 +314,13 @@
public void testGetDevicesMatchingConnectionStatesConnected() {
ArrayList<BluetoothDevice> expected = new ArrayList<BluetoothDevice>();
expected.add(mDevice1);
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
List<BluetoothDevice> devices =
- mService.getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_CONNECTED});
+ mService.getDevicesMatchingConnectionStates(new int[] {STATE_CONNECTED});
assertThat(devices).isEqualTo(expected);
+ assertThat(mLooper.nextMessage()).isNull();
}
/**
@@ -345,67 +332,55 @@
ArrayList<BluetoothDevice> expected = new ArrayList<BluetoothDevice>();
expected.add(mDevice1);
expected.add(mDevice2);
- expected.add(mDevice3);
- expected.add(mDevice4);
- expected.add(mDevice5);
- expected.add(mDevice6);
List<BluetoothDevice> devices =
- mService.getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_DISCONNECTED});
+ mService.getDevicesMatchingConnectionStates(new int[] {STATE_DISCONNECTED});
assertThat(devices).isEqualTo(expected);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that GetConnectionPolicy() can get a device with policy "Allowed" */
@Test
public void testGetConnectionPolicyDeviceAllowed() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- assertThat(mService.getConnectionPolicy(mDevice1))
- .isEqualTo(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
+ assertThat(mService.getConnectionPolicy(mDevice1)).isEqualTo(CONNECTION_POLICY_ALLOWED);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that GetConnectionPolicy() can get a device with policy "Forbidden" */
@Test
public void testGetConnectionPolicyDeviceForbidden() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
- assertThat(mService.getConnectionPolicy(mDevice1))
- .isEqualTo(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_FORBIDDEN);
+ assertThat(mService.getConnectionPolicy(mDevice1)).isEqualTo(CONNECTION_POLICY_FORBIDDEN);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that GetConnectionPolicy() can get a device with policy "Unknown" */
@Test
public void testGetConnectionPolicyDeviceUnknown() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
- assertThat(mService.getConnectionPolicy(mDevice1))
- .isEqualTo(BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_UNKNOWN);
+ assertThat(mService.getConnectionPolicy(mDevice1)).isEqualTo(CONNECTION_POLICY_UNKNOWN);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that SetConnectionPolicy() can change a device's policy to "Allowed" */
@Test
public void testSetConnectionPolicyDeviceAllowed() {
- assertThat(
- mService.setConnectionPolicy(
- mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED))
- .isTrue();
+ assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_ALLOWED)).isTrue();
verify(mDatabaseManager)
.setProfileConnectionPolicy(
- mDevice1,
- BluetoothProfile.A2DP_SINK,
- BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_ALLOWED);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that SetConnectionPolicy() can change a device's policy to "Forbidden" */
@Test
public void testSetConnectionPolicyDeviceForbiddenWhileNotConnected() {
- assertThat(
- mService.setConnectionPolicy(
- mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN))
- .isTrue();
+ assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_FORBIDDEN)).isTrue();
verify(mDatabaseManager)
.setProfileConnectionPolicy(
- mDevice1,
- BluetoothProfile.A2DP_SINK,
- BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+ mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_FORBIDDEN);
+ assertThat(mLooper.nextMessage()).isNull();
}
/**
@@ -414,57 +389,48 @@
*/
@Test
public void testSetConnectionPolicyDeviceForbiddenWhileConnected() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
- assertThat(
- mService.setConnectionPolicy(
- mDevice1, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN))
- .isTrue();
+ assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_FORBIDDEN)).isTrue();
verify(mDatabaseManager)
.setProfileConnectionPolicy(
- mDevice1,
- BluetoothProfile.A2DP_SINK,
- BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+ mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_FORBIDDEN);
- syncHandler(A2dpSinkStateMachine.DISCONNECT);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT);
verify(mNativeInterface).disconnectA2dpSink(eq(mDevice1));
- assertThat(mService.getConnectionState(mDevice1))
- .isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mService.getConnectionState(mDevice1)).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP, -1 /* SM_QUIT_CMD */);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that SetConnectionPolicy() can change a device's policy to "Unknown" */
@Test
public void testSetConnectionPolicyDeviceUnknown() {
- assertThat(
- mService.setConnectionPolicy(
- mDevice1, BluetoothProfile.CONNECTION_POLICY_UNKNOWN))
- .isTrue();
+ assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_UNKNOWN)).isTrue();
verify(mDatabaseManager)
.setProfileConnectionPolicy(
- mDevice1,
- BluetoothProfile.A2DP_SINK,
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
+ mDevice1, BluetoothProfile.A2DP_SINK, CONNECTION_POLICY_UNKNOWN);
+ assertThat(mLooper.nextMessage()).isNull();
}
/** Test that SetConnectionPolicy is robust to DatabaseManager failures */
@Test
public void testSetConnectionPolicyDatabaseWriteFails() {
- when(mDatabaseManager.setProfileConnectionPolicy(any(), anyInt(), anyInt()))
- .thenReturn(false);
- assertThat(
- mService.setConnectionPolicy(
- mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED))
- .isFalse();
+ doReturn(false)
+ .when(mDatabaseManager)
+ .setProfileConnectionPolicy(any(), anyInt(), anyInt());
+ assertThat(mService.setConnectionPolicy(mDevice1, CONNECTION_POLICY_ALLOWED)).isFalse();
+ assertThat(mLooper.nextMessage()).isNull();
}
@Test
public void testDumpDoesNotCrash() {
- mockDevicePriority(mDevice1, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
+ mockDevicePriority(mDevice1, CONNECTION_POLICY_ALLOWED);
setupDeviceConnection(mDevice1);
mService.dump(new StringBuilder());
+ assertThat(mLooper.nextMessage()).isNull();
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java
index 55aeb0b..c635bfa 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java
@@ -15,10 +15,13 @@
*/
package com.android.bluetooth.a2dpsink;
+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 com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -45,46 +48,33 @@
@RunWith(AndroidJUnit4.class)
public class A2dpSinkStateMachineTest {
- private static final String DEVICE_ADDRESS = "11:11:11:11:11:11";
- private static final int UNHANDLED_MESSAGE = 9999;
-
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock private A2dpSinkService mService;
@Mock private A2dpSinkNativeInterface mNativeInterface;
+ private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+ private final BluetoothDevice mDevice = mAdapter.getRemoteDevice("11:11:11:11:11:11");
+
private A2dpSinkStateMachine mStateMachine;
- private BluetoothAdapter mAdapter;
- private BluetoothDevice mDevice;
private TestLooper mLooper;
@Before
public void setUp() throws Exception {
mLooper = new TestLooper();
- mAdapter = BluetoothAdapter.getDefaultAdapter();
- assertThat(mAdapter).isNotNull();
- mDevice = mAdapter.getRemoteDevice(DEVICE_ADDRESS);
-
- doNothing().when(mService).removeStateMachine(any(A2dpSinkStateMachine.class));
-
mStateMachine =
- new A2dpSinkStateMachine(mLooper.getLooper(), mDevice, mService, mNativeInterface);
- mStateMachine.start();
+ new A2dpSinkStateMachine(mService, mDevice, mLooper.getLooper(), mNativeInterface);
syncHandler(-2 /* SM_INIT_CMD */);
assertThat(mStateMachine.getDevice()).isEqualTo(mDevice);
assertThat(mStateMachine.getAudioConfig()).isNull();
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
}
@After
public void tearDown() throws Exception {
assertThat(mLooper.nextMessage()).isNull();
-
- mStateMachine = null;
- mDevice = null;
- mAdapter = null;
}
private void syncHandler(int... what) {
@@ -97,16 +87,16 @@
private void sendConnectionEvent(int state) {
mStateMachine.sendMessage(
- A2dpSinkStateMachine.STACK_EVENT,
+ A2dpSinkStateMachine.MESSAGE_STACK_EVENT,
StackEvent.connectionStateChanged(mDevice, state));
- syncHandler(A2dpSinkStateMachine.STACK_EVENT);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT);
}
private void sendAudioConfigChangedEvent(int sampleRate, int channelCount) {
mStateMachine.sendMessage(
- A2dpSinkStateMachine.STACK_EVENT,
+ A2dpSinkStateMachine.MESSAGE_STACK_EVENT,
StackEvent.audioConfigChanged(mDevice, sampleRate, channelCount));
- syncHandler(A2dpSinkStateMachine.STACK_EVENT);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_STACK_EVENT);
}
/**********************************************************************************************
@@ -116,37 +106,37 @@
@Test
public void testConnectInDisconnected() {
mStateMachine.connect();
- syncHandler(A2dpSinkStateMachine.CONNECT);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT);
verify(mNativeInterface).connectA2dpSink(mDevice);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
}
@Test
public void testDisconnectInDisconnected() {
mStateMachine.disconnect();
- syncHandler(A2dpSinkStateMachine.DISCONNECT);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
}
@Test
public void testAudioConfigChangedInDisconnected() {
sendAudioConfigChangedEvent(44, 1);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
assertThat(mStateMachine.getAudioConfig()).isNull();
}
@Test
public void testIncomingConnectedInDisconnected() {
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ sendConnectionEvent(STATE_CONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
}
@Test
public void testAllowedIncomingConnectionInDisconnected() {
mockDeviceConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ sendConnectionEvent(STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
verify(mNativeInterface, times(0)).connectA2dpSink(mDevice);
}
@@ -154,24 +144,24 @@
public void testForbiddenIncomingConnectionInDisconnected() {
mockDeviceConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTING);
+ sendConnectionEvent(STATE_CONNECTING);
verify(mNativeInterface).disconnectA2dpSink(mDevice);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
}
@Test
public void testUnknownIncomingConnectionInDisconnected() {
mockDeviceConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ sendConnectionEvent(STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
verify(mNativeInterface, times(0)).connectA2dpSink(mDevice);
}
@Test
public void testIncomingDisconnectInDisconnected() {
- sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ sendConnectionEvent(STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
@@ -179,19 +169,20 @@
@Test
public void testIncomingDisconnectingInDisconnected() {
- sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ sendConnectionEvent(STATE_DISCONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
verify(mService, times(0)).removeStateMachine(mStateMachine);
}
@Test
public void testIncomingConnectingInDisconnected() {
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ sendConnectionEvent(STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
}
@Test
public void testUnhandledMessageInDisconnected() {
+ final int UNHANDLED_MESSAGE = 9999;
mStateMachine.sendMessage(UNHANDLED_MESSAGE);
mStateMachine.sendMessage(UNHANDLED_MESSAGE, 0 /* arbitrary payload */);
syncHandler(UNHANDLED_MESSAGE, UNHANDLED_MESSAGE);
@@ -205,32 +196,32 @@
public void testConnectedInConnecting() {
testConnectInDisconnected();
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ sendConnectionEvent(STATE_CONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
}
@Test
public void testConnectingInConnecting() {
testConnectInDisconnected();
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ sendConnectionEvent(STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
}
@Test
public void testDisconnectingInConnecting() {
testConnectInDisconnected();
- sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ sendConnectionEvent(STATE_DISCONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
}
@Test
public void testDisconnectedInConnecting() {
testConnectInDisconnected();
- sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ sendConnectionEvent(STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
@@ -241,8 +232,8 @@
testConnectInDisconnected();
mLooper.moveTimeForward(120_000); // Skip time so the timeout fires
- syncHandler(A2dpSinkStateMachine.CONNECT_TIMEOUT);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT_TIMEOUT);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
@@ -253,7 +244,7 @@
testConnectInDisconnected();
sendAudioConfigChangedEvent(44, 1);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
assertThat(mStateMachine.getAudioConfig()).isNull();
}
@@ -262,8 +253,8 @@
testConnectInDisconnected();
mStateMachine.connect();
- syncHandler(A2dpSinkStateMachine.CONNECT);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
}
@Test
@@ -271,16 +262,16 @@
testConnectInDisconnected();
mStateMachine.disconnect();
- syncHandler(A2dpSinkStateMachine.DISCONNECT);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTING);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTING);
// send connected, disconnect should get processed
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ sendConnectionEvent(STATE_CONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
- syncHandler(A2dpSinkStateMachine.DISCONNECT); // message was defer
+ syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT); // message was defer
verify(mNativeInterface).disconnectA2dpSink(mDevice);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
@@ -295,8 +286,8 @@
testConnectedInConnecting();
mStateMachine.connect();
- syncHandler(A2dpSinkStateMachine.CONNECT);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_CONNECT);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
}
@Test
@@ -304,9 +295,9 @@
testConnectedInConnecting();
mStateMachine.disconnect();
- syncHandler(A2dpSinkStateMachine.DISCONNECT);
+ syncHandler(A2dpSinkStateMachine.MESSAGE_DISCONNECT);
verify(mNativeInterface).disconnectA2dpSink(mDevice);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
@@ -317,7 +308,7 @@
testConnectedInConnecting();
sendAudioConfigChangedEvent(44, 1);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
BluetoothAudioConfig expected =
new BluetoothAudioConfig(44, 1, AudioFormat.ENCODING_PCM_16BIT);
@@ -328,24 +319,24 @@
public void testConnectedInConnected() {
testConnectedInConnecting();
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ sendConnectionEvent(STATE_CONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
}
@Test
public void testConnectingInConnected() {
testConnectedInConnecting();
- sendConnectionEvent(BluetoothProfile.STATE_CONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ sendConnectionEvent(STATE_CONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_CONNECTED);
}
@Test
public void testDisconnectingInConnected() {
testConnectedInConnecting();
- sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTING);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ sendConnectionEvent(STATE_DISCONNECTING);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
@@ -355,8 +346,8 @@
public void testDisconnectedInConnected() {
testConnectedInConnecting();
- sendConnectionEvent(BluetoothProfile.STATE_DISCONNECTED);
- assertThat(mStateMachine.getState()).isEqualTo(BluetoothProfile.STATE_DISCONNECTED);
+ sendConnectionEvent(STATE_DISCONNECTED);
+ assertThat(mStateMachine.getState()).isEqualTo(STATE_DISCONNECTED);
syncHandler(A2dpSinkStateMachine.CLEANUP);
verify(mService).removeStateMachine(mStateMachine);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java
index 7f73380..1f19faa 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java
@@ -19,6 +19,7 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
import androidx.test.runner.AndroidJUnit4;
@@ -48,22 +49,22 @@
@Test
public void testCreateConnectionStateChangedDisconnectedEvent() {
- testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_DISCONNECTED);
+ testConnectionStateChangedBase(BluetoothProfile.STATE_DISCONNECTED);
}
@Test
public void testCreateConnectionStateChangedConnectingEvent() {
- testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_CONNECTING);
+ testConnectionStateChangedBase(BluetoothProfile.STATE_CONNECTING);
}
@Test
public void testCreateConnectionStateChangedConnectedEvent() {
- testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_CONNECTED);
+ testConnectionStateChangedBase(BluetoothProfile.STATE_CONNECTED);
}
@Test
public void testCreateConnectionStateChangedDisconnectingEvent() {
- testConnectionStateChangedBase(StackEvent.CONNECTION_STATE_DISCONNECTING);
+ testConnectionStateChangedBase(BluetoothProfile.STATE_DISCONNECTING);
}
private void testConnectionStateChangedBase(int state) {
diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java
index deabdbe..4aeb448 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java
@@ -31,8 +31,6 @@
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.support.v4.media.session.PlaybackStateCompat;
import androidx.test.InstrumentationRegistry;
@@ -44,7 +42,6 @@
import com.android.bluetooth.a2dpsink.A2dpSinkService;
import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService.BrowseResult;
import com.android.bluetooth.btservice.AdapterService;
-import com.android.bluetooth.flags.Flags;
import org.junit.After;
import org.junit.Before;
@@ -69,8 +66,6 @@
private AvrcpControllerService mService = null;
private BluetoothAdapter mAdapter = null;
- @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
@Rule
public final ServiceTestRule mBluetoothBrowserMediaServiceTestRule = new ServiceTestRule();
@@ -516,7 +511,6 @@
* first device by checking that it has remained as the active device.
*/
@Test
- @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
public void testActiveDeviceMaintainsAudioFocusWhenOtherDeviceConnects_audioFocusMaintained() {
mService.onConnectionStateChanged(true, true, mRemoteDevice);
// check set active device is called
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 70fac79..dbe35e1 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
@@ -31,7 +31,6 @@
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Looper;
-import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.support.v4.media.MediaMetadataCompat;
@@ -467,21 +466,7 @@
/** Get the root of the device */
@Test
- @DisableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
- public void testGetDeviceRootNode_flagRandomDeviceIdDisabled_rootNodeMatchesUuidFormat() {
- // create new state machine to follow current flags rule
- mAvrcpStateMachine = makeStateMachine(mTestDevice);
- setUpConnectedState(true, true);
- final String rootName = "__ROOT__" + mTestDevice.getAddress().toString();
- // Get the root of the device
- BrowseTree.BrowseNode results = mAvrcpStateMachine.findNode(rootName);
- Assert.assertEquals(rootName, results.getID());
- }
-
- /** Get the root of the device */
- @Test
- @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
- public void testGetDeviceRootNode_flagRandomDeviceIdEnabled_rootNodeMatchesUuidFormat() {
+ public void testGetDeviceRootNode_rootNodeMatchesUuidFormat() {
// create new state machine to follow current flags rule
mAvrcpStateMachine = makeStateMachine(mTestDevice);
setUpConnectedState(true, true);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java
index f91b44e..6241e65 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java
@@ -21,7 +21,6 @@
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -80,19 +79,7 @@
}
@Test
- @DisableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
- public void constructor_withBluetoothDevice() {
- BrowseNode browseNode = mBrowseTree.new BrowseNode(mTestDevice);
-
- assertThat(browseNode.getID()).isNotNull();
- assertThat(browseNode.getDevice()).isEqualTo(mTestDevice);
- assertThat(browseNode.isPlayer()).isFalse();
- assertThat(browseNode.isBrowsable()).isTrue();
- }
-
- @Test
- @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
- public void constructor_withBluetoothDevice_withRandomUuid() {
+ public void constructor_withBluetoothDevice_createsRandomUuid() {
BrowseNode browseNode1 = mBrowseTree.new BrowseNode(mTestDevice);
assertThat(browseNode1.getID()).isNotNull();
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 d27dcbd..275b394 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
@@ -20,15 +20,10 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
import com.android.bluetooth.avrcpcontroller.BrowseTree.BrowseNode;
-import com.android.bluetooth.flags.Flags;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import java.util.Set;
@@ -38,8 +33,6 @@
private static final String TEST_HANDLE = "test_handle";
private static final String TEST_NODE_ID = "test_node_id";
- @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
private final byte[] mTestAddress = new byte[] {01, 01, 01, 01, 01, 01};
private BluetoothAdapter mAdapter;
private BluetoothDevice mTestDevice = null;
@@ -102,7 +95,6 @@
}
@Test
- @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
public void sameDeviceDifferentBrowseTrees_uniqueMediaIds() {
BrowseTree browseTree1 = new BrowseTree(mTestDevice);
BrowseTree browseTree2 = new BrowseTree(mTestDevice);
@@ -120,14 +112,6 @@
}
@Test
- @DisableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
- public void findBrowseNodeByIDForDevice() {
- BrowseTree browseTree = new BrowseTree(mTestDevice);
- final String deviceId = BrowseTree.ROOT + mTestDevice.getAddress().toString();
- assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode);
- }
-
- @Test
public void findBrowseNodeByIDForIllegalId() {
BrowseTree browseTree = new BrowseTree(mTestDevice);
assertThat(browseTree.findBrowseNodeByID(ILLEGAL_ID)).isNull();
@@ -143,8 +127,7 @@
}
@Test
- @EnableFlags(Flags.FLAG_RANDOMIZE_DEVICE_LEVEL_MEDIA_IDS)
- public void findBrowseNodeByIDForDevice_withRandomDeviceID_nodeIsFound() {
+ public void findBrowseNodeByIDForDevice_nodeIsFound() {
BrowseTree browseTree = new BrowseTree(mTestDevice);
final String deviceId = browseTree.mRootNode.getID();
assertThat(browseTree.findBrowseNodeByID(deviceId)).isEqualTo(browseTree.mRootNode);
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 12a0f7d..e6e9f40 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
@@ -2039,6 +2039,40 @@
}
}
+ @Test
+ @EnableFlags(Flags.FLAG_LEAUDIO_BROADCAST_API_GET_LOCAL_METADATA)
+ public void testGetSourceMetadata() {
+ prepareConnectedDeviceGroup();
+ startSearchingForSources();
+ onScanResult(mSourceDevice, TEST_BROADCAST_ID);
+ onSyncEstablished(mSourceDevice, TEST_SYNC_HANDLE);
+ BluetoothLeBroadcastMetadata meta = createBroadcastMetadata(TEST_BROADCAST_ID);
+
+ for (BassClientStateMachine sm : mStateMachines.values()) {
+ injectRemoteSourceStateSourceAdded(
+ sm,
+ meta,
+ TEST_SOURCE_ID,
+ BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED,
+ meta.isEncrypted()
+ ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING
+ : BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED,
+ null);
+ doReturn(null).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID));
+ assertThat(mBassClientService.getSourceMetadata(sm.getDevice(), TEST_SOURCE_ID))
+ .isEqualTo(null);
+
+ doReturn(meta).when(sm).getCurrentBroadcastMetadata(eq(TEST_SOURCE_ID));
+ doReturn(true).when(sm).isSyncedToTheSource(eq(TEST_SOURCE_ID));
+ assertThat(mBassClientService.getSourceMetadata(sm.getDevice(), TEST_SOURCE_ID))
+ .isEqualTo(meta);
+ }
+
+ for (BassClientStateMachine sm : mStateMachines.values()) {
+ injectRemoteSourceStateRemoval(sm, TEST_SOURCE_ID);
+ }
+ }
+
/** Test whether the group operation flag is set on addSource() and removed on removeSource */
@Test
public void testGroupStickyFlagSetUnset() {
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 541f965..9acb612 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
@@ -383,6 +383,24 @@
}
@Test
+ public void headsetRemoveActive_fallbackToLeAudio() {
+ when(mHeadsetService.getFallbackDevice()).thenReturn(mHeadsetDevice);
+
+ leAudioConnected(mLeAudioDevice);
+ mTestLooper.dispatchAll();
+ verify(mLeAudioService, times(1)).setActiveDevice(mLeAudioDevice);
+
+ headsetConnected(mHeadsetDevice, false);
+ mTestLooper.dispatchAll();
+ verify(mHeadsetService).setActiveDevice(mHeadsetDevice);
+
+ // HFP activce device to null. Expect to fallback to LeAudio.
+ headsetActiveDeviceChanged(null);
+ mTestLooper.dispatchAll();
+ verify(mLeAudioService, times(2)).setActiveDevice(mLeAudioDevice);
+ }
+
+ @Test
public void a2dpConnectedButHeadsetNotConnected_setA2dpActive() {
when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_IN_CALL);
a2dpConnected(mA2dpHeadsetDevice, true);
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 1f9540f..7372288 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
@@ -45,7 +45,6 @@
import com.android.bluetooth.hid.HidHostNativeInterface;
import com.android.bluetooth.le_audio.LeAudioNativeInterface;
import com.android.bluetooth.pan.PanNativeInterface;
-import com.android.bluetooth.vc.VolumeControlNativeInterface;
import org.junit.After;
import org.junit.Assert;
@@ -94,7 +93,6 @@
@Mock private PanNativeInterface mPanNativeInterface;
@Mock private CsipSetCoordinatorNativeInterface mCsipSetCoordinatorInterface;
@Mock private LeAudioNativeInterface mLeAudioInterface;
- @Mock private VolumeControlNativeInterface mVolumeControlInterface;
private void setProfileState(int profile, int state) {
FutureTask task =
@@ -157,6 +155,7 @@
.filter(
profile ->
profile != BluetoothProfile.HAP_CLIENT
+ && profile != BluetoothProfile.VOLUME_CONTROL
&& profile != BluetoothProfile.GATT)
.toArray();
TestUtils.setAdapterService(mAdapterService);
@@ -175,7 +174,6 @@
PanNativeInterface.setInstance(mPanNativeInterface);
CsipSetCoordinatorNativeInterface.setInstance(mCsipSetCoordinatorInterface);
LeAudioNativeInterface.setInstance(mLeAudioInterface);
- VolumeControlNativeInterface.setInstance(mVolumeControlInterface);
}
@After
@@ -196,7 +194,6 @@
PanNativeInterface.setInstance(null);
CsipSetCoordinatorNativeInterface.setInstance(null);
LeAudioNativeInterface.setInstance(null);
- VolumeControlNativeInterface.setInstance(null);
}
/**
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java
index 4f26e51..81c4865 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientServiceTest.java
@@ -17,8 +17,14 @@
package com.android.bluetooth.hap;
-import static android.bluetooth.BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED;
+import static android.bluetooth.BluetoothDevice.BOND_BONDED;
+import static android.bluetooth.BluetoothDevice.BOND_BONDING;
+import static android.bluetooth.BluetoothDevice.BOND_NONE;
import static android.bluetooth.BluetoothHapClient.ACTION_HAP_DEVICE_AVAILABLE;
+import static android.bluetooth.BluetoothHapClient.PRESET_INDEX_UNAVAILABLE;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
import static android.bluetooth.BluetoothProfile.EXTRA_PREVIOUS_STATE;
import static android.bluetooth.BluetoothProfile.EXTRA_STATE;
import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
@@ -31,13 +37,12 @@
import static com.google.common.truth.Truth.assertThat;
import static org.hamcrest.core.AllOf.allOf;
-import static org.mockito.Mockito.after;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -51,8 +56,11 @@
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothHapClientCallback;
+import android.content.Intent;
import android.os.Binder;
import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
@@ -64,8 +72,9 @@
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.csip.CsipSetCoordinatorService;
+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;
@@ -74,6 +83,7 @@
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;
@@ -82,17 +92,10 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
-import java.util.concurrent.TimeoutException;
@MediumTest
@RunWith(AndroidJUnit4.class)
public class HapClientServiceTest {
- private static final int TIMEOUT_MS = 1000;
- private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
- private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 0);
- private final BluetoothDevice mDevice2 = TestUtils.getTestDevice(mAdapter, 1);
- private final BluetoothDevice mDevice3 = TestUtils.getTestDevice(mAdapter, 2);
-
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
@Mock private AdapterService mAdapterService;
@@ -103,22 +106,34 @@
@Mock private IBluetoothHapClientCallback mFrameworkCallback;
@Mock private Binder mBinder;
+ private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+ private final BluetoothDevice mDevice = TestUtils.getTestDevice(mAdapter, 0);
+ private final BluetoothDevice mDevice2 = TestUtils.getTestDevice(mAdapter, 1);
+ private final BluetoothDevice mDevice3 = TestUtils.getTestDevice(mAdapter, 2);
+
private HapClientService mService;
private HapClientNativeCallback mNativeCallback;
+ private InOrder mInOrder;
+ private TestLooper mLooper;
@Before
- public void setUp() throws Exception {
- HapClientStateMachine.sConnectTimeoutMs = TIMEOUT_MS;
-
- doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
+ public void setUp() {
doReturn(mDevice).when(mAdapterService).getDeviceFromByte(eq(getByteAddress(mDevice)));
doReturn(mDevice2).when(mAdapterService).getDeviceFromByte(eq(getByteAddress(mDevice2)));
doReturn(mDevice3).when(mAdapterService).getDeviceFromByte(eq(getByteAddress(mDevice3)));
+ doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
+
+ doReturn(CONNECTION_POLICY_ALLOWED)
+ .when(mDatabaseManager)
+ .getProfileConnectionPolicy(any(), anyInt());
doReturn(mCsipService).when(mServiceFactory).getCsipSetCoordinatorService();
doReturn(mBinder).when(mFrameworkCallback).asBinder();
+ doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
+ doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
+
/* Prepare CAS groups */
doReturn(List.of(0x02, 0x03)).when(mCsipService).getAllGroupIds(BluetoothUuid.CAP);
@@ -147,8 +162,13 @@
.getRemoteUuids(any(BluetoothDevice.class));
doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
- startService();
+ mInOrder = inOrder(mAdapterService);
+ mLooper = new TestLooper();
+
+ mService = new HapClientService(mAdapterService, mLooper.getLooper(), mNativeInterface);
+ mService.setAvailable(true);
mNativeCallback = new HapClientNativeCallback(mAdapterService, mService);
+
mService.mFactory = mServiceFactory;
synchronized (mService.mCallbacks) {
mService.mCallbacks.register(mFrameworkCallback);
@@ -156,257 +176,114 @@
}
@After
- public void tearDown() throws Exception {
- if (mService == null) {
- return;
- }
-
+ public void tearDown() {
synchronized (mService.mCallbacks) {
mService.mCallbacks.unregister(mFrameworkCallback);
}
- stopService();
- }
-
- private void startService() throws TimeoutException {
- mService = new HapClientService(mAdapterService, mNativeInterface);
- mService.start();
- mService.setAvailable(true);
- }
-
- private void stopService() throws TimeoutException {
mService.stop();
- mService = HapClientService.getHapClientService();
- Assert.assertNull(mService);
+ assertThat(HapClientService.getHapClientService()).isNull();
}
@Test
- public void testGetHapService() {
- Assert.assertEquals(mService, HapClientService.getHapClientService());
+ public void getHapService() {
+ assertThat(HapClientService.getHapClientService()).isEqualTo(mService);
}
@Test
- public void testGetSetPolicy() throws Exception {
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
- Assert.assertEquals(
- "Initial device policy",
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
- mService.getConnectionPolicy(mDevice));
-
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
- Assert.assertEquals(
- "Setting device policy to POLICY_FORBIDDEN",
- BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
- mService.getConnectionPolicy(mDevice));
-
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- int policy = mService.getConnectionPolicy(mDevice);
- Assert.assertEquals(
- "Setting device policy to POLICY_ALLOWED",
- BluetoothProfile.CONNECTION_POLICY_ALLOWED,
- policy);
+ public void getConnectionPolicy() {
+ for (int policy :
+ List.of(
+ CONNECTION_POLICY_UNKNOWN,
+ CONNECTION_POLICY_FORBIDDEN,
+ CONNECTION_POLICY_ALLOWED)) {
+ doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt());
+ assertThat(mService.getConnectionPolicy(mDevice)).isEqualTo(policy);
+ }
}
@Test
- public void testGetPolicyAfterStopped() {
- mService.stop();
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
- Assert.assertEquals(
- "Initial device policy",
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
- mService.getConnectionPolicy(mDevice));
- }
-
- @Test
- public void testOkToConnect() {
+ public void canConnect_whenNotBonded_returnFalse() {
int badPolicyValue = 1024;
int badBondState = 42;
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_NONE,
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
- false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_NONE,
- BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
- false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_NONE,
- BluetoothProfile.CONNECTION_POLICY_ALLOWED,
- false);
- testOkToConnectCase(mDevice, BluetoothDevice.BOND_NONE, badPolicyValue, false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_BONDING,
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
- false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_BONDING,
- BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
- false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_BONDING,
- BluetoothProfile.CONNECTION_POLICY_ALLOWED,
- false);
- testOkToConnectCase(mDevice, BluetoothDevice.BOND_BONDING, badPolicyValue, false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_BONDED,
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN,
- true);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_BONDED,
- BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
- false);
- testOkToConnectCase(
- mDevice,
- BluetoothDevice.BOND_BONDED,
- BluetoothProfile.CONNECTION_POLICY_ALLOWED,
- true);
- testOkToConnectCase(mDevice, BluetoothDevice.BOND_BONDED, badPolicyValue, false);
- testOkToConnectCase(
- mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_UNKNOWN, false);
- testOkToConnectCase(
- mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN, false);
- testOkToConnectCase(
- mDevice, badBondState, BluetoothProfile.CONNECTION_POLICY_ALLOWED, false);
- testOkToConnectCase(mDevice, badBondState, badPolicyValue, false);
+ for (int bondState : List.of(BOND_NONE, BOND_BONDING, badBondState)) {
+ for (int policy :
+ List.of(
+ CONNECTION_POLICY_UNKNOWN,
+ CONNECTION_POLICY_FORBIDDEN,
+ CONNECTION_POLICY_ALLOWED,
+ badPolicyValue)) {
+ doReturn(bondState).when(mAdapterService).getBondState(any());
+ doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt());
+ assertThat(mService.okToConnect(mDevice)).isEqualTo(false);
+ }
+ }
}
@Test
- public void testOutgoingConnectMissingHasUuid() {
- // Update the device policy so okToConnect() returns true
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
- doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
+ public void canConnect_whenBonded() {
+ int badPolicyValue = 1024;
+ doReturn(BOND_BONDED).when(mAdapterService).getBondState(any());
- // Return No UUID
+ for (int policy : List.of(CONNECTION_POLICY_FORBIDDEN, badPolicyValue)) {
+ doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt());
+ assertThat(mService.okToConnect(mDevice)).isEqualTo(false);
+ }
+ for (int policy : List.of(CONNECTION_POLICY_UNKNOWN, CONNECTION_POLICY_ALLOWED)) {
+ doReturn(policy).when(mDatabaseManager).getProfileConnectionPolicy(any(), anyInt());
+ assertThat(mService.okToConnect(mDevice)).isEqualTo(true);
+ }
+ }
+
+ @Test
+ public void connectToDevice_whenUuidIsMissing_returnFalse() {
doReturn(new ParcelUuid[] {})
.when(mAdapterService)
.getRemoteUuids(any(BluetoothDevice.class));
- // Send a connect request
- Assert.assertFalse("Connect expected to fail", mService.connect(mDevice));
+ assertThat(mService.connect(mDevice)).isFalse();
}
@Test
- public void testOutgoingConnectExistingHasUuid() {
- // Update the device policy so okToConnect() returns true
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
- doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
+ public void connectToDevice_whenPolicyForbid_returnFalse() {
+ doReturn(CONNECTION_POLICY_FORBIDDEN)
+ .when(mDatabaseManager)
+ .getProfileConnectionPolicy(any(), anyInt());
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
-
- // Send a connect request
- Assert.assertTrue("Connect expected to succeed", mService.connect(mDevice));
-
- verify(mAdapterService, timeout(TIMEOUT_MS)).sendBroadcastMultiplePermissions(any(), any());
+ assertThat(mService.connect(mDevice)).isFalse();
}
@Test
- public void testOutgoingConnectPolicyForbidden() {
- doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
- doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
+ public void outgoingConnect_whenTimeOut_isDisconnected() {
+ assertThat(mService.connect(mDevice)).isTrue();
+ mLooper.dispatchAll();
- // Set the device policy to POLICY_FORBIDDEN so connect() should fail
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+ verifyConnectionStateIntent(mDevice, STATE_CONNECTING, STATE_DISCONNECTED);
- // Send a connect request
- Assert.assertFalse("Connect expected to fail", mService.connect(mDevice));
+ mLooper.moveTimeForward(HapClientStateMachine.CONNECT_TIMEOUT.toMillis());
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTING);
}
@Test
- public void testOutgoingConnectTimeout() throws Exception {
- InOrder order = inOrder(mAdapterService);
+ public void connectTwoDevices() {
+ testConnectingDevice(mDevice);
+ testConnectingDevice(mDevice2);
- // Update the device policy so okToConnect() returns true
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
- doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
-
- // Send a connect request
- Assert.assertTrue("Connect failed", mService.connect(mDevice));
-
- order.verify(mAdapterService, timeout(TIMEOUT_MS))
- .sendBroadcastMultiplePermissions(
- argThat(
- allOf(
- hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
- hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice),
- hasExtra(EXTRA_STATE, STATE_CONNECTING),
- hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED))),
- any());
-
- Assert.assertEquals(
- BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(mDevice));
-
- // Verify the connection state broadcast, and that we are in Disconnected state via binder
- order.verify(mAdapterService, timeout(HapClientStateMachine.sConnectTimeoutMs * 2L))
- .sendBroadcastMultiplePermissions(
- argThat(
- allOf(
- hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
- hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice),
- hasExtra(EXTRA_STATE, STATE_DISCONNECTED),
- hasExtra(EXTRA_PREVIOUS_STATE, STATE_CONNECTING))),
- any());
-
- int state = mService.getConnectionState(mDevice);
- Assert.assertEquals(BluetoothProfile.STATE_DISCONNECTED, state);
+ assertThat(mService.getConnectedDevices()).containsExactly(mDevice, mDevice2);
}
@Test
- public void testConnectTwo() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
-
- // Send a connect request for the 1st device
- testConnectingDevice(order, mDevice);
-
- // Send a connect request for the 2nd device
- BluetoothDevice Device2 = TestUtils.getTestDevice(mAdapter, 1);
- testConnectingDevice(order, Device2);
-
- List<BluetoothDevice> devices = mService.getConnectedDevices();
- Assert.assertTrue(devices.contains(mDevice));
- Assert.assertTrue(devices.contains(Device2));
- Assert.assertNotEquals(mDevice, Device2);
+ public void getActivePresetIndex_whenNoConnected_isUnavailable() {
+ assertThat(mService.getActivePresetIndex(mDevice)).isEqualTo(PRESET_INDEX_UNAVAILABLE);
}
@Test
- public void testCallsForNotConnectedDevice() {
- Assert.assertEquals(
- BluetoothHapClient.PRESET_INDEX_UNAVAILABLE,
- mService.getActivePresetIndex(mDevice));
- }
-
- @Test
- public void testGetHapGroupCoordinatedOps() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
- testConnectingDevice(order, mDevice2);
- testConnectingDevice(order, mDevice3);
+ public void testGetHapGroupCoordinatedOps() {
+ testConnectingDevice(mDevice);
+ testConnectingDevice(mDevice2);
+ testConnectingDevice(mDevice3);
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice), 0x04);
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice3), 0x04);
@@ -418,26 +295,22 @@
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice2), 0);
/* Two devices support coordinated operations thus shall report valid group ID */
- Assert.assertEquals(2, mService.getHapGroup(mDevice));
- Assert.assertEquals(3, mService.getHapGroup(mDevice3));
+ assertThat(mService.getHapGroup(mDevice)).isEqualTo(2);
+ assertThat(mService.getHapGroup(mDevice3)).isEqualTo(3);
/* Third one has no coordinated operations support but is part of the group */
int hapGroup = mService.getHapGroup(mDevice2);
- Assert.assertEquals(2, hapGroup);
+ assertThat(hapGroup).isEqualTo(2);
}
@Test
- public void testSelectPresetNative() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
+ public void testSelectPresetNative() throws RemoteException {
+ testConnectingDevice(mDevice);
// Verify Native Interface call
mService.selectPreset(mDevice, 0x00);
verify(mNativeInterface, never()).selectActivePreset(eq(mDevice), eq(0x00));
- verify(mFrameworkCallback, after(TIMEOUT_MS))
+ verify(mFrameworkCallback)
.onPresetSelectionFailed(
eq(mDevice), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX));
@@ -446,19 +319,15 @@
}
@Test
- public void testGroupSelectActivePresetNative() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice3);
+ public void testGroupSelectActivePresetNative() throws RemoteException {
+ testConnectingDevice(mDevice3);
int flags = 0x01;
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice3), flags);
// Verify Native Interface call
mService.selectPresetForGroup(0x03, 0x00);
- verify(mFrameworkCallback, after(TIMEOUT_MS))
+ verify(mFrameworkCallback)
.onPresetSelectionForGroupFailed(
eq(0x03), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX));
@@ -468,11 +337,7 @@
@Test
public void testSwitchToNextPreset() {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
+ testConnectingDevice(mDevice);
// Verify Native Interface call
mService.switchToNextPreset(mDevice);
@@ -481,11 +346,7 @@
@Test
public void testSwitchToNextPresetForGroup() {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice3);
+ testConnectingDevice(mDevice3);
int flags = 0x01;
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice3), flags);
@@ -496,11 +357,7 @@
@Test
public void testSwitchToPreviousPreset() {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
+ testConnectingDevice(mDevice);
// Verify Native Interface call
mService.switchToPreviousPreset(mDevice);
@@ -509,12 +366,8 @@
@Test
public void testSwitchToPreviousPresetForGroup() {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
- testConnectingDevice(order, mDevice2);
+ testConnectingDevice(mDevice);
+ testConnectingDevice(mDevice2);
int flags = 0x01;
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice), flags);
@@ -525,56 +378,40 @@
}
@Test
- public void testGetActivePresetIndex() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
+ public void testGetActivePresetIndex() throws RemoteException {
+ testConnectingDevice(mDevice);
testOnPresetSelected(mDevice, 0x01);
- // Verify cached value via binder
- int presetIndex = mService.getActivePresetIndex(mDevice);
- Assert.assertEquals(0x01, presetIndex);
+ assertThat(mService.getActivePresetIndex(mDevice)).isEqualTo(0x01);
}
@Test
- public void testGetPresetInfoAndActivePresetInfo() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice2);
+ public void testGetPresetInfoAndActivePresetInfo() throws RemoteException {
+ testConnectingDevice(mDevice2);
// Check when active preset is not known yet
List<BluetoothHapPresetInfo> presetList = mService.getAllPresetInfo(mDevice2);
BluetoothHapPresetInfo presetInfo = mService.getPresetInfo(mDevice2, 0x01);
- Assert.assertTrue(presetList.contains(presetInfo));
- Assert.assertEquals(0x01, presetInfo.getIndex());
+ assertThat(presetList).contains(presetInfo);
+ assertThat(presetInfo.getIndex()).isEqualTo(0x01);
- Assert.assertEquals(
- BluetoothHapClient.PRESET_INDEX_UNAVAILABLE,
- mService.getActivePresetIndex(mDevice2));
- Assert.assertEquals(null, mService.getActivePresetInfo(mDevice2));
+ assertThat(mService.getActivePresetIndex(mDevice2)).isEqualTo(PRESET_INDEX_UNAVAILABLE);
+ assertThat(mService.getActivePresetInfo(mDevice2)).isNull();
// Inject active preset change event
testOnPresetSelected(mDevice2, 0x01);
// Check when active preset is known
- Assert.assertEquals(0x01, mService.getActivePresetIndex(mDevice2));
+ assertThat(mService.getActivePresetIndex(mDevice2)).isEqualTo(0x01);
BluetoothHapPresetInfo info = mService.getActivePresetInfo(mDevice2);
- Assert.assertNotNull(info);
- Assert.assertEquals("One", info.getName());
+ assertThat(info).isNotNull();
+ assertThat(info.getName()).isEqualTo("One");
}
@Test
- public void testSetPresetNameNative() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
- testConnectingDevice(order, mDevice);
+ public void testSetPresetNameNative() throws RemoteException {
+ testConnectingDevice(mDevice);
mService.setPresetName(mDevice, 0x00, "ExamplePresetName");
verify(mNativeInterface, never())
@@ -589,26 +426,22 @@
}
@Test
- public void testSetPresetNameForGroup() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
+ public void testSetPresetNameForGroup() throws RemoteException {
int test_group = 0x02;
- testConnectingDevice(order, mDevice);
- testConnectingDevice(order, mDevice2);
+ testConnectingDevice(mDevice);
+ testConnectingDevice(mDevice2);
int flags = 0x21;
mNativeCallback.onFeaturesUpdate(getByteAddress(mDevice), flags);
mService.setPresetNameForGroup(test_group, 0x00, "ExamplePresetName");
- verify(mFrameworkCallback, after(TIMEOUT_MS))
+ verify(mFrameworkCallback)
.onSetPresetNameForGroupFailed(
eq(test_group), eq(BluetoothStatusCodes.ERROR_HAP_INVALID_PRESET_INDEX));
mService.setPresetNameForGroup(-1, 0x01, "ExamplePresetName");
- verify(mFrameworkCallback, after(TIMEOUT_MS))
+ verify(mFrameworkCallback)
.onSetPresetNameForGroupFailed(
eq(-1), eq(BluetoothStatusCodes.ERROR_CSIP_INVALID_GROUP_ID));
@@ -635,7 +468,7 @@
}
@Test
- public void testStackEventOnPresetSelected() throws Exception {
+ public void testStackEventOnPresetSelected() throws RemoteException {
int presetIndex = 0x01;
mNativeCallback.onActivePresetSelected(getByteAddress(mDevice), presetIndex);
@@ -649,7 +482,7 @@
}
@Test
- public void testStackEventOnActivePresetSelectError() throws Exception {
+ public void testStackEventOnActivePresetSelectError() throws RemoteException {
mNativeCallback.onActivePresetSelectError(getByteAddress(mDevice), 0x05);
verify(mFrameworkCallback)
@@ -658,14 +491,8 @@
}
@Test
- public void testStackEventOnPresetInfo() throws Exception {
- InOrder order = inOrder(mAdapterService);
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
-
- // Connect and inject initial presets
- testConnectingDevice(order, mDevice);
+ public void testStackEventOnPresetInfo() throws RemoteException {
+ testConnectingDevice(mDevice);
int infoReason = HapClientStackEvent.PRESET_INFO_REASON_PRESET_INFO_UPDATE;
BluetoothHapPresetInfo[] info = {
@@ -686,17 +513,18 @@
eq(BluetoothStatusCodes.REASON_REMOTE_REQUEST));
List<BluetoothHapPresetInfo> presets = presetsCaptor.getValue();
- Assert.assertEquals(3, presets.size());
+ assertThat(presets.size()).isEqualTo(3);
Optional<BluetoothHapPresetInfo> preset =
presetsCaptor.getValue().stream().filter(p -> 0x01 == p.getIndex()).findFirst();
- Assert.assertEquals("OneChangedToUnavailable", preset.get().getName());
- Assert.assertFalse(preset.get().isAvailable());
- Assert.assertTrue(preset.get().isWritable());
+ assertThat(preset.get().getName()).isEqualTo("OneChangedToUnavailable");
+ assertThat(preset.get().isAvailable()).isFalse();
+ ;
+ assertThat(preset.get().isWritable()).isTrue();
}
@Test
- public void testStackEventOnPresetNameSetError() throws Exception {
+ public void testStackEventOnPresetNameSetError() throws RemoteException {
/* Not a valid name length */
mNativeCallback.onPresetNameSetError(
getByteAddress(mDevice),
@@ -736,7 +564,7 @@
}
@Test
- public void testStackEventOnGroupPresetNameSetError() throws Exception {
+ public void testStackEventOnGroupPresetNameSetError() throws RemoteException {
int groupId = 0x01;
int presetIndex = 0x04;
/* Not a valid name length */
@@ -776,30 +604,25 @@
}
@Test
- public void testServiceBinderGetDevicesMatchingConnectionStates() throws Exception {
- List<BluetoothDevice> devices = mService.getDevicesMatchingConnectionStates(null);
- Assert.assertEquals(0, devices.size());
+ public void getDevicesMatchingConnectionStates_whenNull_isEmpty() {
+ assertThat(mService.getDevicesMatchingConnectionStates(null)).isEmpty();
}
@Test
- public void testServiceBinderSetConnectionPolicy() throws Exception {
- Assert.assertTrue(
- mService.setConnectionPolicy(mDevice, BluetoothProfile.CONNECTION_POLICY_UNKNOWN));
+ public void setConnectionPolicy() {
+ assertThat(mService.setConnectionPolicy(mDevice, CONNECTION_POLICY_UNKNOWN)).isTrue();
verify(mDatabaseManager)
.setProfileConnectionPolicy(
- mDevice,
- BluetoothProfile.HAP_CLIENT,
- BluetoothProfile.CONNECTION_POLICY_UNKNOWN);
+ mDevice, BluetoothProfile.HAP_CLIENT, CONNECTION_POLICY_UNKNOWN);
}
@Test
- public void testServiceBinderGetFeatures() throws Exception {
- int features = mService.getFeatures(mDevice);
- Assert.assertEquals(0x00, features);
+ public void getFeatures() {
+ assertThat(mService.getFeatures(mDevice)).isEqualTo(0x00);
}
@Test
- public void testServiceBinderRegisterUnregisterCallback() throws Exception {
+ public void registerUnregisterCallback() {
IBluetoothHapClientCallback callback = Mockito.mock(IBluetoothHapClientCallback.class);
Binder binder = Mockito.mock(Binder.class);
when(callback.asBinder()).thenReturn(binder);
@@ -807,101 +630,51 @@
synchronized (mService.mCallbacks) {
int size = mService.mCallbacks.getRegisteredCallbackCount();
mService.registerCallback(callback);
- Assert.assertEquals(size + 1, mService.mCallbacks.getRegisteredCallbackCount());
+ assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size + 1);
mService.unregisterCallback(callback);
- Assert.assertEquals(size, mService.mCallbacks.getRegisteredCallbackCount());
+ assertThat(mService.mCallbacks.getRegisteredCallbackCount()).isEqualTo(size);
}
}
@Test
- public void testDumpDoesNotCrash() {
- // Update the device policy so okToConnect() returns true
- when(mDatabaseManager.getProfileConnectionPolicy(mDevice, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
- doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
-
- doReturn(new ParcelUuid[] {BluetoothUuid.HAS})
- .when(mAdapterService)
- .getRemoteUuids(any(BluetoothDevice.class));
-
+ public void dumpDoesNotCrash() {
// Add state machine for testing dump()
mService.connect(mDevice);
-
- verify(mAdapterService, timeout(TIMEOUT_MS)).sendBroadcastMultiplePermissions(any(), any());
+ mLooper.dispatchAll();
mService.dump(new StringBuilder());
}
/** Helper function to test device connecting */
- private void prepareConnectingDevice(BluetoothDevice device) {
- // Prepare intent queue and all the mocks
- when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HAP_CLIENT))
- .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
- doReturn(true).when(mNativeInterface).connectHapClient(any(BluetoothDevice.class));
- doReturn(true).when(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
+ private void testConnectingDevice(BluetoothDevice device) {
+ assertThat(mService.connect(device)).isTrue();
+ mLooper.dispatchAll();
+ verifyConnectingDevice(device);
}
/** Helper function to test device connecting */
- private void testConnectingDevice(InOrder order, BluetoothDevice device) {
- prepareConnectingDevice(device);
- // Send a connect request
- Assert.assertTrue("Connect expected to succeed", mService.connect(device));
- verifyConnectingDevice(order, device);
- }
+ private void verifyConnectingDevice(BluetoothDevice device) {
+ verifyConnectionStateIntent(device, STATE_CONNECTING, STATE_DISCONNECTED);
+ generateConnectionMessageFromNative(device, STATE_CONNECTED, STATE_CONNECTING);
- /** Helper function to test device connecting */
- private void verifyConnectingDevice(InOrder order, BluetoothDevice device) {
- // Verify the connection state broadcast, and that we are in Connecting state
- order.verify(mAdapterService, timeout(TIMEOUT_MS))
- .sendBroadcastMultiplePermissions(
- argThat(
- allOf(
- hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
- hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
- hasExtra(EXTRA_STATE, STATE_CONNECTING),
- hasExtra(EXTRA_PREVIOUS_STATE, STATE_DISCONNECTED))),
- any());
- Assert.assertEquals(BluetoothProfile.STATE_CONNECTING, mService.getConnectionState(device));
-
- // Send a message to trigger connection completed
HapClientStackEvent evt =
- new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- evt.device = device;
- evt.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- mService.messageFromNative(evt);
-
- // Verify the connection state broadcast, and that we are in Connected state
- order.verify(mAdapterService, timeout(TIMEOUT_MS))
- .sendBroadcastMultiplePermissions(
- argThat(
- allOf(
- hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
- hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
- hasExtra(EXTRA_STATE, STATE_CONNECTED),
- hasExtra(EXTRA_PREVIOUS_STATE, STATE_CONNECTING))),
- any());
- Assert.assertEquals(BluetoothProfile.STATE_CONNECTED, mService.getConnectionState(device));
-
- evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
+ new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
evt.device = device;
evt.valueInt1 = 0x01; // features
mService.messageFromNative(evt);
+ mLooper.dispatchAll();
- order.verify(mAdapterService, timeout(TIMEOUT_MS))
- .sendBroadcastMultiplePermissions(
- argThat(
- allOf(
- hasAction(ACTION_HAP_DEVICE_AVAILABLE),
- hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
- hasExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x01))),
- any());
+ verifyIntentSent(
+ hasAction(ACTION_HAP_DEVICE_AVAILABLE),
+ hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
+ hasExtra(BluetoothHapClient.EXTRA_HAP_FEATURES, 0x01));
evt = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_FEATURES);
evt.device = device;
evt.valueInt1 = 0x01; // features
mService.messageFromNative(evt);
+ mLooper.dispatchAll();
// Inject some initial presets
List<BluetoothHapPresetInfo> presets =
@@ -923,29 +696,21 @@
device, HapClientStackEvent.PRESET_INFO_REASON_ALL_PRESET_INFO, presets);
}
- private void testOnPresetSelected(BluetoothDevice device, int index) throws Exception {
+ private void testOnPresetSelected(BluetoothDevice device, int index) throws RemoteException {
HapClientStackEvent evt =
new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_ON_ACTIVE_PRESET_SELECTED);
evt.device = device;
evt.valueInt1 = index;
mService.messageFromNative(evt);
+ mLooper.dispatchAll();
- verify(mFrameworkCallback, after(TIMEOUT_MS))
+ verify(mFrameworkCallback)
.onPresetSelected(
eq(device),
eq(evt.valueInt1),
eq(BluetoothStatusCodes.REASON_LOCAL_STACK_REQUEST));
}
- /** Helper function to test okToConnect() method */
- private void testOkToConnectCase(
- BluetoothDevice device, int bondState, int policy, boolean expected) {
- doReturn(bondState).when(mAdapterService).getBondState(device);
- when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HAP_CLIENT))
- .thenReturn(policy);
- Assert.assertEquals(expected, mService.okToConnect(device));
- }
-
/** Helper function to get byte array for a device address */
private byte[] getByteAddress(BluetoothDevice device) {
if (device == null) {
@@ -953,4 +718,32 @@
}
return Utils.getBytesFromAddress(device.getAddress());
}
+
+ @SafeVarargs
+ private void verifyIntentSent(Matcher<Intent>... matchers) {
+ mInOrder.verify(mAdapterService)
+ .sendBroadcastMultiplePermissions(
+ MockitoHamcrest.argThat(AllOf.allOf(matchers)), any());
+ }
+
+ private void verifyConnectionStateIntent(BluetoothDevice device, int newState, int prevState) {
+ verifyIntentSent(
+ hasAction(BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED),
+ hasExtra(BluetoothDevice.EXTRA_DEVICE, device),
+ hasExtra(EXTRA_STATE, newState),
+ hasExtra(EXTRA_PREVIOUS_STATE, prevState));
+ assertThat(mService.getConnectionState(device)).isEqualTo(newState);
+ }
+
+ private void generateConnectionMessageFromNative(
+ BluetoothDevice device, int newState, int oldState) {
+ HapClientStackEvent event =
+ new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.device = device;
+ event.valueInt1 = newState;
+ mService.messageFromNative(event);
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(device, newState, oldState);
+ }
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java
index d307a5c..249914b 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java
@@ -37,28 +37,6 @@
eventStr = event.toString();
assertThat(eventStr).contains("EVENT_TYPE_UNKNOWN");
- event = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- event.valueInt1 = -1;
- eventStr = event.toString();
- assertThat(eventStr).contains("EVENT_TYPE_CONNECTION_STATE_CHANGED");
- assertThat(eventStr).contains("CONNECTION_STATE_UNKNOWN");
-
- event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTED;
- eventStr = event.toString();
- assertThat(eventStr).contains("CONNECTION_STATE_DISCONNECTED");
-
- event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING;
- eventStr = event.toString();
- assertThat(eventStr).contains("CONNECTION_STATE_CONNECTING");
-
- event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- eventStr = event.toString();
- assertThat(eventStr).contains("CONNECTION_STATE_CONNECTED");
-
- event.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTING;
- eventStr = event.toString();
- assertThat(eventStr).contains("CONNECTION_STATE_DISCONNECTING");
-
event = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
eventStr = event.toString();
assertThat(eventStr).contains("EVENT_TYPE_DEVICE_AVAILABLE");
diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java
index a61e4ea..1c25fad 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java
@@ -17,373 +17,253 @@
package com.android.bluetooth.hap;
+import static android.bluetooth.BluetoothHapClient.ACTION_HAP_CONNECTION_STATE_CHANGED;
+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 com.android.bluetooth.hap.HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED;
+import static com.android.bluetooth.hap.HapClientStateMachine.CONNECT_TIMEOUT;
+import static com.android.bluetooth.hap.HapClientStateMachine.MESSAGE_CONNECT;
+import static com.android.bluetooth.hap.HapClientStateMachine.MESSAGE_DISCONNECT;
+import static com.android.bluetooth.hap.HapClientStateMachine.MESSAGE_STACK_EVENT;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothProfile;
import android.content.Intent;
-import android.os.HandlerThread;
-import android.os.Message;
+import android.os.test.TestLooper;
-import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
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.hamcrest.Matcher;
+import org.hamcrest.core.AllOf;
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;
-@MediumTest
+@SmallTest
@RunWith(AndroidJUnit4.class)
public class HapClientStateMachineTest {
- private BluetoothAdapter mAdapter;
- private HandlerThread mHandlerThread;
- private HapClientStateMachine mHapClientStateMachine;
- private BluetoothDevice mTestDevice;
- private static final int TIMEOUT_MS = 1000;
- boolean mIsAdapterServiceSet;
-
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
- @Mock private AdapterService mAdapterService;
- @Mock private HapClientService mHapClientService;
- @Mock private HapClientNativeInterface mHearingAccessGattClientInterface;
+ @Mock private HapClientService mService;
+ @Mock private HapClientNativeInterface mNativeInterface;
+
+ private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
+ private final BluetoothDevice mDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05");
+
+ private HapClientStateMachine mStateMachine;
+ private InOrder mInOrder;
+ private TestLooper mLooper;
@Before
public void setUp() throws Exception {
- TestUtils.setAdapterService(mAdapterService);
- mIsAdapterServiceSet = true;
+ doReturn(true).when(mService).okToConnect(any());
- mAdapter = BluetoothAdapter.getDefaultAdapter();
+ doReturn(true).when(mNativeInterface).connectHapClient(any());
+ doReturn(true).when(mNativeInterface).disconnectHapClient(any());
- // Get a device for testing
- mTestDevice = mAdapter.getRemoteDevice("00:01:02:03:04:05");
+ mInOrder = inOrder(mService);
+ mLooper = new TestLooper();
- // Set up thread and looper
- mHandlerThread = new HandlerThread("HapClientStateMachineTestHandlerThread");
- mHandlerThread.start();
- mHapClientStateMachine =
- new HapClientStateMachine(
- mTestDevice,
- mHapClientService,
- mHearingAccessGattClientInterface,
- mHandlerThread.getLooper());
- // Override the timeout value to speed up the test
- HapClientStateMachine.sConnectTimeoutMs = 1000; // 1s
- mHapClientStateMachine.start();
- }
-
- @After
- public void tearDown() throws Exception {
- if (!mIsAdapterServiceSet) {
- return;
- }
- if (mHapClientStateMachine != null) {
- mHapClientStateMachine.doQuit();
- mHandlerThread.quit();
- }
- TestUtils.clearAdapterService(mAdapterService);
- }
-
- /** Test that default state is disconnected */
- @Test
- public void testDefaultDisconnectedState() {
- Assert.assertEquals(
- BluetoothProfile.STATE_DISCONNECTED, mHapClientStateMachine.getConnectionState());
- }
-
- /**
- * Allow/disallow connection to any device.
- *
- * @param allow if true, connection is allowed
- */
- private void allowConnection(boolean allow) {
- doReturn(allow).when(mHapClientService).okToConnect(any(BluetoothDevice.class));
- }
-
- /** Test that an incoming connection with policy forbidding connection is rejected */
- @Test
- public void testIncomingPolicyReject() {
- allowConnection(false);
-
- // Inject an event for when incoming connection is requested
- HapClientStackEvent connStCh =
- new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connStCh);
-
- // Verify that no connection state broadcast is executed
- verify(mHapClientService, after(TIMEOUT_MS).never())
- .sendBroadcast(any(Intent.class), anyString());
- // Check that we are in Disconnected state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class));
- }
-
- /** Test that an incoming connection with policy allowing connection is accepted */
- @Test
- public void testIncomingPolicyAccept() {
- allowConnection(true);
-
- // Inject an event for when incoming connection is requested
- HapClientStackEvent connStCh =
- new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING;
- mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connStCh);
-
- // Verify that one connection state broadcast is executed
- ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class);
- verify(mHapClientService, timeout(TIMEOUT_MS))
- .sendBroadcastWithMultiplePermissions(
- intentArgument1.capture(), any(String[].class));
- Assert.assertEquals(
- BluetoothProfile.STATE_CONNECTING,
- intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
-
- // Check that we are in Connecting state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Connecting.class));
-
- // Send a message to trigger connection completed
- HapClientStackEvent connCompletedEvent =
- new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connCompletedEvent.device = mTestDevice;
- connCompletedEvent.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connCompletedEvent);
-
- // Verify that the expected number of broadcasts are executed:
- // - two calls to broadcastConnectionState(): Disconnected -> Connecting -> Connected
- ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class);
- verify(mHapClientService, timeout(TIMEOUT_MS).times(2))
- .sendBroadcastWithMultiplePermissions(
- intentArgument2.capture(), any(String[].class));
- // Check that we are in Connected state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Connected.class));
- }
-
- /** Test that an outgoing connection times out */
- @Test
- public void testOutgoingTimeout() {
- allowConnection(true);
- doReturn(true)
- .when(mHearingAccessGattClientInterface)
- .connectHapClient(any(BluetoothDevice.class));
- doReturn(true)
- .when(mHearingAccessGattClientInterface)
- .disconnectHapClient(any(BluetoothDevice.class));
-
- // Send a connect request
- mHapClientStateMachine.sendMessage(HapClientStateMachine.CONNECT, mTestDevice);
-
- // Verify that one connection state broadcast is executed
- ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class);
- verify(mHapClientService, timeout(TIMEOUT_MS))
- .sendBroadcastWithMultiplePermissions(
- intentArgument1.capture(), any(String[].class));
- Assert.assertEquals(
- BluetoothProfile.STATE_CONNECTING,
- intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
-
- // Check that we are in Connecting state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Connecting.class));
-
- // Verify that one connection state broadcast is executed
- ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class);
- verify(mHapClientService, timeout(HapClientStateMachine.sConnectTimeoutMs * 2L).times(2))
- .sendBroadcastWithMultiplePermissions(
- intentArgument2.capture(), any(String[].class));
- Assert.assertEquals(
- BluetoothProfile.STATE_DISCONNECTED,
- intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
-
- // Check that we are in Disconnected state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class));
- verify(mHearingAccessGattClientInterface).disconnectHapClient(eq(mTestDevice));
- }
-
- /** Test that an incoming connection times out */
- @Test
- public void testIncomingTimeout() {
- allowConnection(true);
- doReturn(true)
- .when(mHearingAccessGattClientInterface)
- .connectHapClient(any(BluetoothDevice.class));
- doReturn(true)
- .when(mHearingAccessGattClientInterface)
- .disconnectHapClient(any(BluetoothDevice.class));
-
- // Inject an event for when incoming connection is requested
- HapClientStackEvent connStCh =
- new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING;
- mHapClientStateMachine.sendMessage(HapClientStateMachine.STACK_EVENT, connStCh);
-
- // Verify that one connection state broadcast is executed
- ArgumentCaptor<Intent> intentArgument1 = ArgumentCaptor.forClass(Intent.class);
- verify(mHapClientService, timeout(TIMEOUT_MS))
- .sendBroadcastWithMultiplePermissions(
- intentArgument1.capture(), any(String[].class));
- Assert.assertEquals(
- BluetoothProfile.STATE_CONNECTING,
- intentArgument1.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
-
- // Check that we are in Connecting state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Connecting.class));
-
- // Verify that one connection state broadcast is executed
- ArgumentCaptor<Intent> intentArgument2 = ArgumentCaptor.forClass(Intent.class);
- verify(mHapClientService, timeout(HapClientStateMachine.sConnectTimeoutMs * 2L).times(2))
- .sendBroadcastWithMultiplePermissions(
- intentArgument2.capture(), any(String[].class));
- Assert.assertEquals(
- BluetoothProfile.STATE_DISCONNECTED,
- intentArgument2.getValue().getIntExtra(BluetoothProfile.EXTRA_STATE, -1));
-
- // Check that we are in Disconnected state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class));
- verify(mHearingAccessGattClientInterface).disconnectHapClient(eq(mTestDevice));
+ mStateMachine =
+ new HapClientStateMachine(mService, mDevice, mNativeInterface, mLooper.getLooper());
}
@Test
- public void testStatesChangesWithMessages() {
- allowConnection(true);
- doReturn(true)
- .when(mHearingAccessGattClientInterface)
- .connectHapClient(any(BluetoothDevice.class));
-
- // Check that we are in Disconnected state
- Assert.assertThat(
- mHapClientStateMachine.getCurrentState(),
- IsInstanceOf.instanceOf(HapClientStateMachine.Disconnected.class));
-
- mHapClientStateMachine.sendMessage(HapClientStateMachine.DISCONNECT);
- // verify disconnectHapClient was called
- verify(mHearingAccessGattClientInterface, timeout(TIMEOUT_MS).times(1))
- .disconnectHapClient(any(BluetoothDevice.class));
-
- // disconnected -> connecting
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT),
- HapClientStateMachine.Connecting.class);
- // connecting -> disconnected
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT_TIMEOUT),
- HapClientStateMachine.Disconnected.class);
-
- // disconnected -> connecting
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT),
- HapClientStateMachine.Connecting.class);
- // connecting -> disconnected
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.DISCONNECT),
- HapClientStateMachine.Disconnected.class);
-
- // disconnected -> connecting
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT),
- HapClientStateMachine.Connecting.class);
- // connecting -> disconnecting
- HapClientStackEvent connStCh =
- new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTING;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Disconnecting.class);
- // disconnecting -> connecting
- connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTING;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Connecting.class);
- // connecting -> connected
- connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Connected.class);
- // connected -> disconnecting
- connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTING;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Disconnecting.class);
- // disconnecting -> disconnected
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.CONNECT_TIMEOUT),
- HapClientStateMachine.Disconnected.class);
-
- // disconnected -> connected
- connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Connected.class);
- // connected -> disconnected
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.DISCONNECT),
- HapClientStateMachine.Disconnected.class);
-
- // disconnected -> connected
- connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_CONNECTED;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Connected.class);
- // connected -> disconnected
- connStCh = new HapClientStackEvent(HapClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- connStCh.device = mTestDevice;
- connStCh.valueInt1 = HapClientStackEvent.CONNECTION_STATE_DISCONNECTED;
- sendMessageAndVerifyTransition(
- mHapClientStateMachine.obtainMessage(HapClientStateMachine.STACK_EVENT, connStCh),
- HapClientStateMachine.Disconnected.class);
+ public void initialState_isDisconnected() {
+ assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_DISCONNECTED);
}
- private <T> void sendMessageAndVerifyTransition(Message msg, Class<T> type) {
- Mockito.clearInvocations(mHapClientService);
- mHapClientStateMachine.sendMessage(msg);
- // Verify that one connection state broadcast is executed
- verify(mHapClientService, timeout(TIMEOUT_MS))
- .sendBroadcastWithMultiplePermissions(any(Intent.class), any(String[].class));
- Assert.assertThat(mHapClientStateMachine.getCurrentState(), IsInstanceOf.instanceOf(type));
+ @Test
+ public void incomingConnect_whenNotOkToConnect_isRejected() {
+ doReturn(false).when(mService).okToConnect(any());
+
+ generateUnexpectedConnectionMessageFromNative(STATE_CONNECTED);
+
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ assertThat(mLooper.nextMessage()).isNull();
+ }
+
+ @Test
+ public void incomingConnect_whenOkToConnect_isConnected() {
+ generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connecting.class);
+
+ generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connected.class);
+ }
+
+ @Test
+ public void outgoingConnect_whenTimeOut_isDisconnectedAndInAcceptList() {
+ sendAndDispatchMessage(MESSAGE_CONNECT);
+ verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connecting.class);
+
+ mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis());
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void incomingConnect_whenTimeOut_isDisconnectedAndInAcceptList() {
+ generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connecting.class);
+
+ mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis());
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void disconnect_whenDisconnected_callNativeDisconnect() {
+ mStateMachine.sendMessage(HapClientStateMachine.MESSAGE_DISCONNECT);
+ mLooper.dispatchAll();
+
+ verify(mNativeInterface).disconnectHapClient(any(BluetoothDevice.class));
+ }
+
+ @Test
+ public void timeout_whenOutgoingConnect_isDisconnected() {
+ sendAndDispatchMessage(MESSAGE_CONNECT);
+ verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connecting.class);
+
+ mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis());
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void disconnect_whenConnecting_isDisconnected() {
+ sendAndDispatchMessage(MESSAGE_CONNECT);
+ verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connecting.class);
+
+ sendAndDispatchMessage(MESSAGE_DISCONNECT);
+ verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_CONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void remoteToggleDisconnect_whenConnecting_isDisconnected() {
+ sendAndDispatchMessage(MESSAGE_CONNECT);
+ verifyConnectionStateIntent(STATE_CONNECTING, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Connecting.class);
+
+ generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTING);
+ generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTING);
+ generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING);
+ generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTED);
+
+ mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis());
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_DISCONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void timeout_whenOutgoingDisConnect_isDisconnected() {
+ generateConnectionMessageFromNative(STATE_CONNECTING, STATE_DISCONNECTED);
+ generateConnectionMessageFromNative(STATE_CONNECTED, STATE_CONNECTING);
+ generateConnectionMessageFromNative(STATE_DISCONNECTING, STATE_CONNECTED);
+
+ mLooper.moveTimeForward(CONNECT_TIMEOUT.toMillis());
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(STATE_DISCONNECTED, STATE_DISCONNECTING);
+ assertThat(mStateMachine.getCurrentState())
+ .isInstanceOf(HapClientStateMachine.Disconnected.class);
+ }
+
+ @Test
+ public void incomingConnect_whenDisconnected_isConnected() {
+ generateConnectionMessageFromNative(STATE_CONNECTED, STATE_DISCONNECTED);
+ assertThat(mStateMachine.getConnectionState()).isEqualTo(STATE_CONNECTED);
+ }
+
+ private void sendAndDispatchMessage(int what) {
+ mStateMachine.sendMessage(what);
+ mLooper.dispatchAll();
+ }
+
+ @SafeVarargs
+ private void verifyIntentSent(Matcher<Intent>... matchers) {
+ mInOrder.verify(mService)
+ .sendBroadcastWithMultiplePermissions(
+ MockitoHamcrest.argThat(AllOf.allOf(matchers)), any());
+ }
+
+ private void verifyConnectionStateIntent(int newState, int oldState) {
+ verifyIntentSent(
+ hasAction(ACTION_HAP_CONNECTION_STATE_CHANGED),
+ hasExtra(BluetoothDevice.EXTRA_DEVICE, mDevice),
+ hasExtra(EXTRA_STATE, newState),
+ hasExtra(EXTRA_PREVIOUS_STATE, oldState));
+ assertThat(mStateMachine.getConnectionState()).isEqualTo(newState);
+ }
+
+ private void generateConnectionMessageFromNative(int newState, int oldState) {
+ HapClientStackEvent event = new HapClientStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.device = mDevice;
+ event.valueInt1 = newState;
+
+ mStateMachine.sendMessage(MESSAGE_STACK_EVENT, event);
+ mLooper.dispatchAll();
+
+ verifyConnectionStateIntent(newState, oldState);
+ }
+
+ private void generateUnexpectedConnectionMessageFromNative(int newConnectionState) {
+ HapClientStackEvent event = new HapClientStackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ event.device = mDevice;
+ event.valueInt1 = newConnectionState;
+
+ mStateMachine.sendMessage(MESSAGE_STACK_EVENT, event);
+ mLooper.dispatchAll();
+
+ mInOrder.verify(mService, never()).sendBroadcast(any(), any(), any());
}
}
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 e713084..a438a8e 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
@@ -1924,6 +1924,14 @@
}
@Test
+ public void testCheckAndProcessAndroidAt_handleConnectingTimePolicyNotAllowed() {
+ when(mHeadsetService.getActiveDevice()).thenReturn(mTestDevice);
+ mHeadsetStateMachine.checkAndProcessAndroidAt(
+ "+ANDROID=SINKAUDIOPOLICY,0,2,2", mTestDevice);
+ verify(mHeadsetService).setActiveDevice(null);
+ }
+
+ @Test
public void testCheckAndProcessAndroidAt_replyAndroidAtFeatureRequest() {
// Commands that will be handled
Assert.assertTrue(mHeadsetStateMachine.checkAndProcessAndroidAt("+ANDROID=?", mTestDevice));
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 c70d425..4ae3df5 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
@@ -112,7 +112,8 @@
boolean isCallbackScan = false;
int scannerId = 0;
- appScanStats.recordScanStart(settings, filters, isFilterScan, isCallbackScan, scannerId);
+ appScanStats.recordScanStart(
+ settings, filters, isFilterScan, isCallbackScan, scannerId, "tag");
appScanStats.isRegistered = true;
StringBuilder stringBuilder = new StringBuilder();
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 a6692a3..b33a9c4 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
@@ -291,7 +291,7 @@
ScanClient client = new ScanClient(id, scanSettings, scanFilterList, appUid);
client.stats = appScanStats;
- client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id);
+ client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id, null);
return client;
}
@@ -389,7 +389,7 @@
ScanClient client = new ScanClient(id, scanSettings, scanFilterList);
client.stats = mMockAppScanStats;
- client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id);
+ client.stats.recordScanStart(scanSettings, scanFilterList, isFiltered, false, id, null);
return client;
}
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/TransitionalScanHelperTest.java
index 3176c78..a614fba 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/TransitionalScanHelperTest.java
@@ -174,7 +174,7 @@
mScanHelper.continuePiStartScan(scannerId, mApp);
verify(appScanStats)
- .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId);
+ .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId, null);
verify(mScanManager).startScan(any());
}
@@ -192,7 +192,7 @@
mScanHelper.continuePiStartScan(scannerId, mApp);
verify(appScanStats)
- .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId);
+ .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId, null);
verify(mScanManager)
.startScan(
argThat(
diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java
index 61db244..0811f4e 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlInputDescriptorTest.java
@@ -19,167 +19,161 @@
import static org.mockito.Mockito.*;
-import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
-import androidx.test.filters.MediumTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.bluetooth.flags.Flags;
+import bluetooth.constants.aics.Mute;
-import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-@MediumTest
+@SmallTest
@RunWith(AndroidJUnit4.class)
public class VolumeControlInputDescriptorTest {
+ private static final int NUMBER_OF_INPUT = 3;
+ private static final int NUMBER_OF_FIELD_IN_STRUCT = 9;
+ private static final int VALID_ID = 1;
+ private static final int INVALID_ID = NUMBER_OF_INPUT;
+ private static final int INVALID_ID2 = -1;
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private VolumeControlInputDescriptor mDescriptor;
+
@Before
- public void setUp() throws Exception {
- // placeholder
- }
-
- @After
- public void tearDown() throws Exception {
- // placeholder
+ public void setUp() {
+ mDescriptor = new VolumeControlInputDescriptor(NUMBER_OF_INPUT);
}
@Test
- @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT)
- public void testVolumeControlInputDescriptorInvalidIdOperations() throws Exception {
- VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor();
+ public void dump_noCrash() {
+ StringBuilder sb = new StringBuilder();
- int invalidId = 1;
- int testGainValue = 100;
- int testGainMode = 1;
- boolean testGainMute = true;
- String testDesc = "testDescription";
- int testType = VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_AMBIENT;
- int testGainSettingsMax = 100;
- int testGainSettingsMin = 0;
- int testGainSettingsUnit = 1;
-
- // Test adding all props using invalid ID
- assertThat(descriptor.isActive(invalidId)).isFalse();
- assertThat(descriptor.setActive(invalidId, true)).isFalse();
- assertThat(descriptor.setDescription(invalidId, testDesc)).isFalse();
- assertThat(descriptor.getDescription(invalidId)).isNull();
- assertThat(descriptor.setType(invalidId, testType)).isFalse();
- assertThat(descriptor.getType(invalidId))
- .isEqualTo(VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_UNSPECIFIED);
-
- assertThat(descriptor.getGain(invalidId)).isEqualTo(0);
- assertThat(descriptor.isMuted(invalidId)).isFalse();
- assertThat(
- descriptor.setPropSettings(
- invalidId,
- testGainSettingsUnit,
- testGainSettingsMin,
- testGainSettingsMax))
- .isFalse();
- assertThat(descriptor.setState(invalidId, testGainValue, testGainMode, testGainMute))
- .isFalse();
+ mDescriptor.dump(sb);
+ int nLines = NUMBER_OF_INPUT * (NUMBER_OF_FIELD_IN_STRUCT + 1); // +1 for the id
+ assertThat(sb.toString()).containsMatch("( .*\n){" + nLines + "}");
}
@Test
- @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT)
- public void testVolumeControlInputDescriptorMultipleInstanceAdded() throws Exception {
-
- VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor();
-
- int validId = 10;
-
- // Verify that adding descriptor works increase descriptor size
- assertThat(descriptor.size()).isEqualTo(0);
- descriptor.add(validId);
- assertThat(descriptor.size()).isEqualTo(1);
-
- // Check if adding same id will not increase descriptor count.
- descriptor.add(validId);
- assertThat(descriptor.size()).isEqualTo(1);
+ public void setFoo_withAllValidId_valuesAreUpdated() {
+ for (int i = 0; i < NUMBER_OF_INPUT; i++) {
+ assertThat(mDescriptor.getStatus(i)).isEqualTo(0); // AudioInputStatus.INACTIVE);
+ mDescriptor.setStatus(i, 1); // AudioInputStatus.ACTIVE);
+ assertThat(mDescriptor.getStatus(i)).isEqualTo(1); // AudioInputStatus.ACTIVE);
+ }
}
@Test
- @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT)
- public void testVolumeControlInputDescriptorInstanceRemoveAndClear() throws Exception {
-
- VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor();
-
- int id_1 = 10;
- int id_2 = 20;
- int invalidId = 1;
-
- // Verify that adding descriptor works increase descriptor size
- assertThat(descriptor.size()).isEqualTo(0);
- descriptor.add(id_1);
- assertThat(descriptor.size()).isEqualTo(1);
- descriptor.add(id_2);
-
- // Remove valid id
- descriptor.remove(id_1);
- assertThat(descriptor.size()).isEqualTo(1);
-
- // Remove invalid id not change number of descriptors
- descriptor.remove(invalidId);
- assertThat(descriptor.size()).isEqualTo(1);
-
- // Check clear API
- descriptor.clear();
- assertThat(descriptor.size()).isEqualTo(0);
+ public void getStatus_whenNeverSet_defaultToInactive() {
+ assertThat(mDescriptor.getStatus(VALID_ID)).isEqualTo(0); // AudioInputStatus.INACTIVE);
}
@Test
- @EnableFlags(Flags.FLAG_LEAUDIO_ADD_AICS_SUPPORT)
- public void testVolumeControlInputDescriptorAllValidApiCalls() throws Exception {
+ public void setStatus_withValidId_valueIsUpdated() {
+ int newStatus = 1; // AudioInputStatus.ACTIVE;
+ mDescriptor.setStatus(VALID_ID, newStatus);
- VolumeControlInputDescriptor descriptor = new VolumeControlInputDescriptor();
+ assertThat(mDescriptor.getStatus(VALID_ID)).isEqualTo(newStatus);
+ }
- int validId = 10;
- int testGainValue = 100;
- int testGainMode = 1;
- boolean testGainMute = true;
- String defaultDesc = "";
- String testDesc = "testDescription";
- int testType = VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_AMBIENT;
- int testGainSettingsMax = 100;
- int testGainSettingsMin = 0;
- int testGainSettingsUnit = 1;
+ @Test
+ public void setStatus_withInvalidId_valueIsNotUpdated() {
+ int newStatus = 1; // AudioInputStatus.ACTIVE;
+ mDescriptor.setStatus(INVALID_ID, newStatus);
- descriptor.add(validId);
+ assertThat(mDescriptor.getStatus(INVALID_ID)).isNotEqualTo(newStatus);
+ }
- // Active state
- assertThat(descriptor.isActive(validId)).isFalse();
- assertThat(descriptor.setActive(validId, true)).isTrue();
- assertThat(descriptor.isActive(validId)).isTrue();
+ @Test
+ public void getType_whenNeverSet_defaultToUnspecified() {
+ assertThat(mDescriptor.getType(VALID_ID)).isEqualTo(0); // AudioInputType.UNSPECIFIED);
+ }
- // Descriptor
- assertThat(descriptor.getDescription(validId)).isEqualTo(defaultDesc);
- assertThat(descriptor.setDescription(validId, testDesc)).isTrue();
- assertThat(descriptor.getDescription(validId)).isEqualTo(testDesc);
+ @Test
+ public void setType_withValidId_valueIsUpdated() {
+ int newType = 7; // AudioInputType.AMBIENT;
+ mDescriptor.setType(VALID_ID, newType);
- // Type
- assertThat(descriptor.getType(validId))
- .isEqualTo(VolumeControlInputDescriptor.AUDIO_INPUT_TYPE_UNSPECIFIED);
- assertThat(descriptor.setType(validId, testType)).isTrue();
- assertThat(descriptor.getType(validId)).isEqualTo(testType);
+ assertThat(mDescriptor.getType(VALID_ID)).isEqualTo(newType);
+ }
- // Properties
- assertThat(
- descriptor.setPropSettings(
- validId,
- testGainSettingsUnit,
- testGainSettingsMin,
- testGainSettingsMax))
- .isTrue();
+ @Test
+ public void setType_withInvalidId_valueIsNotUpdated() {
+ int newType = 1; // AudioInputType.BLUETOOTH;
+ mDescriptor.setType(INVALID_ID2, newType);
- // State
- assertThat(descriptor.setState(validId, testGainValue, testGainMode, testGainMute))
- .isTrue();
- assertThat(descriptor.getGain(validId)).isEqualTo(testGainValue);
+ assertThat(mDescriptor.getType(INVALID_ID2)).isNotEqualTo(newType);
+ }
+
+ @Test
+ public void setState_withValidIdButIncorrectSettings_valueIsNotUpdated() {
+ int newGainValue = 42;
+ int newGainMode = 42;
+ int mute = Mute.NOT_MUTED;
+ mDescriptor.setState(VALID_ID, newGainMode, newGainMode, mute);
+
+ assertThat(mDescriptor.getGainSetting(VALID_ID)).isNotEqualTo(newGainValue);
+ // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode);
+ assertThat(mDescriptor.getMute(VALID_ID)).isNotEqualTo(mute);
+ }
+
+ @Test
+ public void setState_withValidIdAndCorrectSettings_valueIsUpdated() {
+ int newMax = 100;
+ int newMin = 0;
+ int newUnit = 1;
+ mDescriptor.setPropSettings(VALID_ID, newUnit, newMin, newMax);
+
+ int newGainValue = 42;
+ int newGainMode = 42;
+ int mute = Mute.MUTED;
+ mDescriptor.setState(VALID_ID, newGainMode, mute, newGainMode);
+
+ assertThat(mDescriptor.getGainSetting(VALID_ID)).isEqualTo(newGainValue);
+ // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode);
+ assertThat(mDescriptor.getMute(VALID_ID)).isEqualTo(mute);
+ }
+
+ @Test
+ public void setState_withInvalidId_valueIsNotUpdated() {
+ int newMax = 100;
+ int newMin = 0;
+ int newUnit = 1;
+ // Should be no-op but we want to copy the working case test, just with an invalid id
+ mDescriptor.setPropSettings(INVALID_ID, newUnit, newMin, newMax);
+
+ int newGainValue = 42;
+ int newGainMode = 42;
+ int mute = Mute.MUTED;
+ mDescriptor.setState(INVALID_ID, newGainMode, newGainMode, mute);
+
+ assertThat(mDescriptor.getGainSetting(INVALID_ID)).isNotEqualTo(newGainValue);
+ // assertThat(mDescriptor.getGainMode(VALID_ID)).isNotEqualTo(newGainMode);
+ assertThat(mDescriptor.getMute(INVALID_ID)).isEqualTo(Mute.DISABLED);
+ }
+
+ @Test
+ public void getDescription_whenNeverSet_defaultToEmptyString() {
+ assertThat(mDescriptor.getDescription(VALID_ID)).isEmpty();
+ }
+
+ @Test
+ public void setDescription_withValidId_valueIsUpdated() {
+ String newDescription = "what a nice description";
+ mDescriptor.setDescription(VALID_ID, newDescription);
+
+ assertThat(mDescriptor.getDescription(VALID_ID)).isEqualTo(newDescription);
+ }
+
+ @Test
+ public void setDescription_withInvalidId_valueIsNotUpdated() {
+ String newDescription = "what a nice description";
+ mDescriptor.setDescription(INVALID_ID, newDescription);
+
+ assertThat(mDescriptor.getDescription(INVALID_ID)).isNotEqualTo(newDescription);
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java
new file mode 100644
index 0000000..51b5f57
--- /dev/null
+++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.vc;
+
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED;
+import static com.android.bluetooth.vc.VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothProfile;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.bluetooth.btservice.AdapterService;
+
+import com.google.common.truth.Expect;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@RunWith(AndroidJUnit4.class)
+public class VolumeControlNativeCallbackTest {
+ @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
+ @Rule public Expect expect = Expect.create();
+
+ @Mock private AdapterService mAdapterService;
+ @Mock private VolumeControlService mService;
+ @Captor private ArgumentCaptor<VolumeControlStackEvent> mEvent;
+
+ private VolumeControlNativeCallback mNativeCallback;
+
+ @Before
+ public void setUp() throws Exception {
+ doReturn(true).when(mService).isAvailable();
+
+ mNativeCallback = new VolumeControlNativeCallback(mAdapterService, mService);
+ }
+
+ @Test
+ public void onConnectionStateChanged() {
+ int state = BluetoothProfile.STATE_CONNECTED;
+
+ mNativeCallback.onConnectionStateChanged(state, null);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_CONNECTION_STATE_CHANGED);
+ expect.that(event.valueInt1).isEqualTo(state);
+ }
+
+ @Test
+ public void onVolumeStateChanged() {
+ int volume = 3;
+ boolean mute = false;
+ int flags = 1;
+ boolean isAutonomous = false;
+
+ mNativeCallback.onVolumeStateChanged(volume, mute, flags, null, isAutonomous);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_VOLUME_STATE_CHANGED);
+ }
+
+ @Test
+ public void onGroupVolumeStateChanged() {
+ int volume = 3;
+ boolean mute = false;
+ int groupId = 1;
+ boolean isAutonomous = false;
+
+ mNativeCallback.onGroupVolumeStateChanged(volume, mute, groupId, isAutonomous);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_VOLUME_STATE_CHANGED);
+ expect.that(event.valueInt1).isEqualTo(groupId);
+ expect.that(event.valueInt2).isEqualTo(volume);
+ expect.that(event.valueBool1).isEqualTo(mute);
+ expect.that(event.valueBool2).isEqualTo(isAutonomous);
+ }
+
+ @Test
+ public void onDeviceAvailable() {
+ int numOfExternalOutputs = 3;
+ int numOfExternalInputs = 0;
+
+ mNativeCallback.onDeviceAvailable(numOfExternalOutputs, numOfExternalInputs, null);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_DEVICE_AVAILABLE);
+ }
+
+ @Test
+ public void onExtAudioOutVolumeOffsetChanged() {
+ int externalOutputId = 2;
+ int offset = 0;
+
+ mNativeCallback.onExtAudioOutVolumeOffsetChanged(externalOutputId, offset, null);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED);
+ }
+
+ @Test
+ public void onExtAudioOutLocationChanged() {
+ int externalOutputId = 2;
+ int location = 100;
+
+ mNativeCallback.onExtAudioOutLocationChanged(externalOutputId, location, null);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED);
+ }
+
+ @Test
+ public void onExtAudioOutDescriptionChanged() {
+ int externalOutputId = 2;
+ String descr = "test-descr";
+
+ mNativeCallback.onExtAudioOutDescriptionChanged(externalOutputId, descr, null);
+ verify(mService).messageFromNative(mEvent.capture());
+ VolumeControlStackEvent event = mEvent.getValue();
+
+ expect.that(event.type).isEqualTo(EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED);
+ }
+
+ @Test
+ public void onExtAudioInStateChanged() {
+ int id = 2;
+ int gainSetting = 1;
+ int gainMode = 0;
+ int mute = 0;
+
+ mNativeCallback.onExtAudioInStateChanged(id, gainSetting, mute, gainMode, null);
+ verify(mService)
+ .onExtAudioInStateChanged(any(), eq(id), eq(gainSetting), eq(mute), eq(gainMode));
+ }
+
+ @Test
+ public void onExtAudioInStatusChanged() {
+ int id = 2;
+ int status = 1;
+
+ mNativeCallback.onExtAudioInStatusChanged(id, status, null);
+ verify(mService).onExtAudioInStatusChanged(any(), eq(id), eq(status));
+ }
+
+ @Test
+ public void onExtAudioInTypeChanged() {
+ int id = 2;
+ int type = 1;
+
+ mNativeCallback.onExtAudioInTypeChanged(id, type, null);
+ verify(mService).onExtAudioInTypeChanged(any(), eq(id), eq(type));
+ }
+
+ @Test
+ public void onExtAudioInDescriptionChanged() {
+ int id = 2;
+ String descr = "microphone";
+
+ mNativeCallback.onExtAudioInDescriptionChanged(id, descr, null);
+ verify(mService).onExtAudioInDescriptionChanged(any(), eq(id), eq(descr));
+ }
+
+ @Test
+ public void onExtAudioInGainPropsChanged() {
+ int id = 2;
+ int unit = 1;
+ int min = 0;
+ int max = 100;
+
+ mNativeCallback.onExtAudioInGainPropsChanged(id, unit, min, max, null);
+ verify(mService).onExtAudioInGainPropsChanged(any(), eq(id), eq(unit), eq(min), eq(max));
+ }
+}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java
deleted file mode 100644
index 9b0aa48..0000000
--- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright 2022 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.vc;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.bluetooth.BluetoothProfile;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@RunWith(AndroidJUnit4.class)
-public class VolumeControlNativeInterfaceTest {
- @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
-
- @Mock private VolumeControlService mService;
-
- private VolumeControlNativeInterface mNativeInterface;
-
- @Before
- public void setUp() throws Exception {
- when(mService.isAvailable()).thenReturn(true);
- VolumeControlService.setVolumeControlService(mService);
- mNativeInterface = VolumeControlNativeInterface.getInstance();
- }
-
- @After
- public void tearDown() {
- VolumeControlService.setVolumeControlService(null);
- }
-
- @Test
- public void onConnectionStateChanged() {
- int state = BluetoothProfile.STATE_CONNECTED;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onConnectionStateChanged(state, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED);
- }
-
- @Test
- public void onVolumeStateChanged() {
- int volume = 3;
- boolean mute = false;
- int flags = 1;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
- boolean isAutonomous = false;
-
- mNativeInterface.onVolumeStateChanged(volume, mute, flags, address, isAutonomous);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
- }
-
- @Test
- public void onGroupVolumeStateChanged() {
- int volume = 3;
- boolean mute = false;
- int groupId = 1;
- boolean isAutonomous = false;
-
- mNativeInterface.onGroupVolumeStateChanged(volume, mute, groupId, isAutonomous);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
- assertThat(event.getValue().valueInt1).isEqualTo(groupId);
- }
-
- @Test
- public void onDeviceAvailable() {
- int numOfExternalOutputs = 3;
- int numOfExternalInputs = 0;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onDeviceAvailable(numOfExternalOutputs, numOfExternalInputs, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_DEVICE_AVAILABLE);
- }
-
- @Test
- public void onExtAudioOutVolumeOffsetChanged() {
- int externalOutputId = 2;
- int offset = 0;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioOutVolumeOffsetChanged(externalOutputId, offset, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_VOL_OFFSET_CHANGED);
- }
-
- @Test
- public void onExtAudioOutLocationChanged() {
- int externalOutputId = 2;
- int location = 100;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioOutLocationChanged(externalOutputId, location, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_LOCATION_CHANGED);
- }
-
- @Test
- public void onExtAudioOutDescriptionChanged() {
- int externalOutputId = 2;
- String descr = "test-descr";
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioOutDescriptionChanged(externalOutputId, descr, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_OUT_DESCRIPTION_CHANGED);
- }
-
- @Test
- public void onExtAudioInStateChanged() {
- int externalInputId = 2;
- int gainValue = 1;
- int gainMode = 0;
- boolean mute = false;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioInStateChanged(
- externalInputId, gainValue, gainMode, mute, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATE_CHANGED);
- }
-
- @Test
- public void onExtAudioInStatusChanged() {
- int externalInputId = 2;
- int status = 1;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioInStatusChanged(externalInputId, status, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_STATUS_CHANGED);
- }
-
- @Test
- public void onExtAudioInTypeChanged() {
- int externalInputId = 2;
- int type = 1;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioInTypeChanged(externalInputId, type, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_TYPE_CHANGED);
- }
-
- @Test
- public void onExtAudioInDescriptionChanged() {
- int externalInputId = 2;
- String descr = "microphone";
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioInDescriptionChanged(externalInputId, descr, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_DESCR_CHANGED);
- }
-
- @Test
- public void onExtAudioInGainPropsChanged() {
- int externalInputId = 2;
- int unit = 1;
- int min = 0;
- int max = 100;
- byte[] address = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
-
- mNativeInterface.onExtAudioInGainPropsChanged(externalInputId, unit, min, max, address);
-
- ArgumentCaptor<VolumeControlStackEvent> event =
- ArgumentCaptor.forClass(VolumeControlStackEvent.class);
- verify(mService).messageFromNative(event.capture());
- assertThat(event.getValue().type)
- .isEqualTo(VolumeControlStackEvent.EVENT_TYPE_EXT_AUDIO_IN_GAIN_PROPS_CHANGED);
- }
-}
diff --git a/android/pandora/OWNERS b/android/pandora/OWNERS
index ffae7f1..c199a82 100644
--- a/android/pandora/OWNERS
+++ b/android/pandora/OWNERS
@@ -1,3 +1,2 @@
# Bug component: 1099313
girardier@google.com
-charliebout@google.com
diff --git a/android/pandora/mmi2grpc/mmi2grpc/vcp.py b/android/pandora/mmi2grpc/mmi2grpc/vcp.py
index fa869ab..95a1a06 100644
--- a/android/pandora/mmi2grpc/mmi2grpc/vcp.py
+++ b/android/pandora/mmi2grpc/mmi2grpc/vcp.py
@@ -145,33 +145,32 @@
# After discovery Android subscribes by itself, after profile connection
return "OK"
- def IUT_SEND_WRITE_REQUEST(self, description: str, **kwargs):
+ @match_description
+ def IUT_SEND_WRITE_REQUEST(self, description: str, chr_name: str, op_code: str, **kwargs):
r"""
- Please send write request to handle 0xXXXX with following value.
- Characteristic name:
- Op Code: [X (0xXX)] Op code name
- Change Counter: <WildCard: Exists>
- Value: <WildCard: Exists>
+ Please send write request to handle 0x([0-9A-Fa-f]{4}) with following value.
+ (?P<chr_name>(Volume Control Point|Volume Offset Control Point)):
+ Op Code: (?P<op_code>((<WildCard: Exists>)|(\[[0-9] \(0x0[0-9]\)\]\s([\w]*\s){1,3})))(.*)
"""
# Wait a couple seconds so the VCP is ready (subscriptions and reads are completed)
sleep(2)
- if ("Set Absolute Volume" in description):
- self.vcp.SetDeviceVolume(connection=self.connection, volume=42)
- elif ("Unmute" in description):
- # for now, there is no way to trigger this, and tests are skipped
+ if (chr_name == "Volume Control Point"):
+ if "Set Absolute Volume" in op_code:
+ self.vcp.SetDeviceVolume(connection=self.connection, volume=42)
+ elif ("Unmute" in op_code):
+ # for now, there is no way to trigger this, and tests are skipped
+ return "No"
+ elif ("<WildCard: Exists>" in op_code):
+ # Handles sending *any* OP Code on Volume Control Point
+ self.vcp.SetDeviceVolume(connection=self.connection, volume=42)
+ elif (chr_name == "Volume Offset Control Point"):
+ if ("Set Volume Offset" in op_code or
+ "<WildCard: Exists>" in op_code):
+ self.vcp.SetVolumeOffset(connection=self.connection, offset=42)
+ else:
return "No"
- elif ("Set Volume Offset" in description):
- self.vcp.SetVolumeOffset(connection=self.connection, offset=42)
- elif ("Volume Control Point" in description and
- "Op Code: <WildCard: Exists>" in description):
- # Handles sending *any* OP Code on Volume Control Point
- self.vcp.SetDeviceVolume(connection=self.connection, volume=42)
- elif ("Volume Offset Control Point" in description and
- "Op Code: <WildCard: Exists>" in description):
- self.vcp.SetVolumeOffset(connection=self.connection, offset=42)
-
return "OK"
diff --git a/android/pandora/test/OWNERS b/android/pandora/test/OWNERS
deleted file mode 100644
index ffae7f1..0000000
--- a/android/pandora/test/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1099313
-girardier@google.com
-charliebout@google.com
diff --git a/common/Android.bp b/common/Android.bp
new file mode 100644
index 0000000..900cc36
--- /dev/null
+++ b/common/Android.bp
@@ -0,0 +1,29 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_library {
+ name: "bluetooth_constants",
+ srcs: [
+ "bluetooth/constants/AudioInputType.aidl",
+ "bluetooth/constants/aics/AudioInputStatus.aidl",
+ "bluetooth/constants/aics/GainMode.aidl",
+ "bluetooth/constants/aics/Mute.aidl",
+ ],
+ visibility: ["//packages/modules/Bluetooth:__subpackages__"],
+}
+
+// other java component doesn't know how to depend on an aidl_library
+java_library {
+ name: "bluetooth_constants_java",
+ srcs: [
+ "bluetooth/constants/AudioInputType.aidl",
+ "bluetooth/constants/aics/AudioInputStatus.aidl",
+ "bluetooth/constants/aics/GainMode.aidl",
+ "bluetooth/constants/aics/Mute.aidl",
+ ],
+ apex_available: ["com.android.btservices"],
+ min_sdk_version: "Tiramisu",
+ sdk_version: "module_current",
+ visibility: ["//packages/modules/Bluetooth:__subpackages__"],
+}
diff --git a/common/OWNERS b/common/OWNERS
new file mode 100644
index 0000000..5b3f4ba
--- /dev/null
+++ b/common/OWNERS
@@ -0,0 +1 @@
+wescande@google.com
diff --git a/common/bluetooth/constants/AudioInputType.aidl b/common/bluetooth/constants/AudioInputType.aidl
new file mode 100644
index 0000000..2dfef1e
--- /dev/null
+++ b/common/bluetooth/constants/AudioInputType.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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 bluetooth.constants;
+
+/**
+ * See Bluetooth SIG Assigned Numbers 6.12.2 Audio Input Type Definitions
+ * {@hide}
+ */
+@JavaDerive(toString = true)
+@Backing(type="int")
+enum AudioInputType {
+ UNSPECIFIED = 0x00,
+ BLUETOOTH = 0x01,
+ MICROPHONE = 0x02,
+ ANALOG = 0x03,
+ DIGITAL = 0x04,
+ RADIO = 0x05,
+ STREAMING = 0x06,
+ AMBIENT = 0x07,
+}
diff --git a/common/bluetooth/constants/aics/AudioInputStatus.aidl b/common/bluetooth/constants/aics/AudioInputStatus.aidl
new file mode 100644
index 0000000..b217e65
--- /dev/null
+++ b/common/bluetooth/constants/aics/AudioInputStatus.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 bluetooth.constants.aics;
+
+/**
+ * See Audio Input Control Service 1.0 - 3.4 Audio Input Status
+ * {@hide}
+ */
+@JavaDerive(toString = true)
+@Backing(type="byte")
+enum AudioInputStatus {
+ INACTIVE = 0x00,
+ ACTIVE = 0x01,
+ // RFU 0x02 - 0xFF
+}
diff --git a/common/bluetooth/constants/aics/GainMode.aidl b/common/bluetooth/constants/aics/GainMode.aidl
new file mode 100644
index 0000000..2f3516a
--- /dev/null
+++ b/common/bluetooth/constants/aics/GainMode.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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 bluetooth.constants.aics;
+
+/**
+ * See Audio Input Control Service 1.0 - 2.2.1.3. Gain_Mode field
+ * The Gain_Mode field shall be set to a value that reflects whether gain modes are manual
+ * or automatic.
+ * - Manual Only, the server allows only manual gain.
+ * - Automatic Only, the server allows only automatic gain.
+ *
+ * For all other Gain_Mode field values, the server allows switchable automatic/manual gain.
+ * {@hide}
+ */
+@JavaDerive(toString = true)
+@Backing(type="byte")
+enum GainMode {
+ MANUAL_ONLY = 0x00,
+ AUTOMATIC_ONLY = 0x01,
+ MANUAL = 0x02,
+ AUTOMATIC = 0x03,
+}
diff --git a/common/bluetooth/constants/aics/Mute.aidl b/common/bluetooth/constants/aics/Mute.aidl
new file mode 100644
index 0000000..ce2af50
--- /dev/null
+++ b/common/bluetooth/constants/aics/Mute.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 bluetooth.constants.aics;
+
+/**
+ * See Audio Input Control Service 1.0 - 2.2.1.2. Mute field
+ * {@hide}
+ */
+@JavaDerive(toString = true)
+@Backing(type="byte")
+enum Mute {
+ NOT_MUTED = 0x00,
+ MUTED = 0x01,
+ DISABLED = 0x02,
+}
diff --git a/flags/Android.bp b/flags/Android.bp
index d5f0c1f..f9b8426 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -43,6 +43,7 @@
"metric.aconfig",
"opp.aconfig",
"pairing.aconfig",
+ "pbapclient.aconfig",
"ranging.aconfig",
"rfcomm.aconfig",
"rnr.aconfig",
diff --git a/flags/BUILD.gn b/flags/BUILD.gn
index ba23368..6f98c23 100644
--- a/flags/BUILD.gn
+++ b/flags/BUILD.gn
@@ -34,6 +34,7 @@
"metric.aconfig",
"opp.aconfig",
"pairing.aconfig",
+ "pbapclient.aconfig",
"ranging.aconfig",
"rfcomm.aconfig",
"rnr.aconfig",
diff --git a/flags/avrcp_controller.aconfig b/flags/avrcp_controller.aconfig
index de205eb..4374eef 100644
--- a/flags/avrcp_controller.aconfig
+++ b/flags/avrcp_controller.aconfig
@@ -2,16 +2,6 @@
container: "com.android.btservices"
flag {
- name: "randomize_device_level_media_ids"
- namespace: "bluetooth"
- description: "Randomize the media id of device level nodes in our browse tree by attaching a randomized string after the UUID, each time a device connects"
- bug: "332367017"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "uncache_player_when_browsed_player_changes"
namespace: "bluetooth"
description: "Uncache media player items when changing to a new player so updated player contents can be fetched if we change back to the previous player"
diff --git a/flags/framework.aconfig b/flags/framework.aconfig
index 32b88d4..255d3a7 100644
--- a/flags/framework.aconfig
+++ b/flags/framework.aconfig
@@ -80,4 +80,12 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
\ No newline at end of file
+}
+
+flag {
+ name: "identity_address_type_api"
+ is_exported: true
+ namespace: "bluetooth"
+ description: "Add a new API to BluetoothDevice to retrieve Identity Address Type"
+ bug: "377171798"
+}
diff --git a/flags/pbapclient.aconfig b/flags/pbapclient.aconfig
new file mode 100644
index 0000000..dbbbb77
--- /dev/null
+++ b/flags/pbapclient.aconfig
@@ -0,0 +1,16 @@
+package: "com.android.bluetooth.flags"
+container: "com.android.btservices"
+
+flag {
+ name: "pbap_client_storage_refactor"
+ namespace: "bluetooth"
+ description: "Abstract away accounts/storage and change how contacts are passed and stored"
+ bug: "376461939"
+}
+
+flag {
+ name: "pbap_client_contacts_caching"
+ namespace: "bluetooth"
+ description: "Use primary and secondary versions to persist contacts across connections"
+ bug: "376461947"
+}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index ebc0542..cd02d18 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -597,6 +597,7 @@
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getMaximumSourceCapacity(@NonNull android.bluetooth.BluetoothDevice);
+ method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_api_get_local_metadata") @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothLeBroadcastMetadata getSourceMetadata(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isSearchInProgress();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void modifySource(@NonNull android.bluetooth.BluetoothDevice, int, @NonNull android.bluetooth.BluetoothLeBroadcastMetadata);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothLeBroadcastAssistant.Callback);
diff --git a/framework/java/android/bluetooth/BluetoothA2dpSink.java b/framework/java/android/bluetooth/BluetoothA2dpSink.java
index 166b4a4..ecaa9d3 100644
--- a/framework/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/framework/java/android/bluetooth/BluetoothA2dpSink.java
@@ -138,11 +138,7 @@
* @hide
*/
@RequiresBluetoothConnectPermission
- @RequiresPermission(
- allOf = {
- BLUETOOTH_CONNECT,
- BLUETOOTH_PRIVILEGED,
- })
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothA2dpSink service = getService();
@@ -311,11 +307,7 @@
* @hide
*/
@RequiresBluetoothConnectPermission
- @RequiresPermission(
- allOf = {
- BLUETOOTH_CONNECT,
- BLUETOOTH_PRIVILEGED,
- })
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
@@ -367,11 +359,7 @@
* @hide
*/
@RequiresBluetoothConnectPermission
- @RequiresPermission(
- allOf = {
- BLUETOOTH_CONNECT,
- BLUETOOTH_PRIVILEGED,
- })
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
@@ -389,11 +377,7 @@
*/
@SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(
- allOf = {
- BLUETOOTH_CONNECT,
- BLUETOOTH_PRIVILEGED,
- })
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
if (VDBG) log("getConnectionPolicy(" + device + ")");
final IBluetoothA2dpSink service = getService();
@@ -419,11 +403,7 @@
*/
@SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(
- allOf = {
- BLUETOOTH_CONNECT,
- BLUETOOTH_PRIVILEGED,
- })
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
public boolean isAudioPlaying(@NonNull BluetoothDevice device) {
if (VDBG) log("isAudioPlaying(" + device + ")");
final IBluetoothA2dpSink service = getService();
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index 3477bed..ebbe975 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -1092,12 +1092,6 @@
BluetoothAdapter(IBluetoothManager managerService, AttributionSource attributionSource) {
mManagerService = requireNonNull(managerService);
mAttributionSource = requireNonNull(attributionSource);
- mServiceLock.writeLock().lock();
- try {
- mService = getBluetoothService(mManagerCallback);
- } finally {
- mServiceLock.writeLock().unlock();
- }
Consumer<IBluetooth> registerQualityReportCallbackConsumer =
(IBluetooth service) -> {
@@ -1165,6 +1159,13 @@
new CallbackWrapper(
registerBluetoothConnectionCallbackConsumer,
unregisterBluetoothConnectionCallbackConsumer);
+
+ mServiceLock.writeLock().lock();
+ try {
+ mService = registerBlueoothManagerCallback(mManagerCallback);
+ } finally {
+ mServiceLock.writeLock().unlock();
+ }
}
/**
@@ -4211,15 +4212,8 @@
}
}
- /**
- * Registers a IBluetoothManagerCallback and returns the cached Bluetooth service proxy object.
- *
- * <p>TODO: rename this API to registerBlueoothManagerCallback or something? the current name
- * does not match what it does very well.
- *
- * <p>/ @UnsupportedAppUsage /*package
- */
- IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
+ /** Registers a IBluetoothManagerCallback and returns the cached service proxy object. */
+ IBluetooth registerBlueoothManagerCallback(IBluetoothManagerCallback cb) {
requireNonNull(cb);
if (Flags.getProfileUseLock()) {
sServiceLock.writeLock().lock();
diff --git a/framework/java/android/bluetooth/BluetoothGatt.java b/framework/java/android/bluetooth/BluetoothGatt.java
index 92d0582..4631953 100644
--- a/framework/java/android/bluetooth/BluetoothGatt.java
+++ b/framework/java/android/bluetooth/BluetoothGatt.java
@@ -299,7 +299,8 @@
TAG,
"onPhyUpdate() -"
+ (" status=" + status)
- + (" address=" + address)
+ + (" address="
+ + BluetoothUtils.toAnonymizedAddress(address))
+ (" txPhy=" + txPhy)
+ (" rxPhy=" + rxPhy));
}
@@ -332,7 +333,8 @@
TAG,
"onPhyRead() -"
+ (" status=" + status)
- + (" address=" + address)
+ + (" address="
+ + BluetoothUtils.toAnonymizedAddress(address))
+ (" txPhy=" + txPhy)
+ (" rxPhy=" + rxPhy));
}
@@ -414,7 +416,12 @@
public void onSearchComplete(
String address, List<BluetoothGattService> services, int status) {
if (DBG) {
- Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
+ Log.d(
+ TAG,
+ "onSearchComplete() = address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " status="
+ + status);
}
if (!address.equals(mDevice.getAddress())) {
return;
@@ -613,8 +620,14 @@
*/
@Override
public void onNotify(String address, int handle, byte[] value) {
- if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
-
+ if (VDBG) {
+ Log.d(
+ TAG,
+ "onNotify() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " handle="
+ + handle);
+ }
if (!address.equals(mDevice.getAddress())) {
return;
}
@@ -646,7 +659,12 @@
@SuppressLint("AndroidFrameworkRequiresPermission")
public void onDescriptorRead(String address, int status, int handle, byte[] value) {
if (VDBG) {
- Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle);
+ Log.d(
+ TAG,
+ "onDescriptorRead() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " handle="
+ + handle);
}
if (!address.equals(mDevice.getAddress())) {
@@ -703,7 +721,12 @@
public void onDescriptorWrite(
String address, int status, int handle, byte[] value) {
if (VDBG) {
- Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle);
+ Log.d(
+ TAG,
+ "onDescriptorWrite() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " handle="
+ + handle);
}
if (!address.equals(mDevice.getAddress())) {
@@ -757,7 +780,12 @@
@Override
public void onExecuteWrite(String address, int status) {
if (VDBG) {
- Log.d(TAG, "onExecuteWrite() - Device=" + address + " status=" + status);
+ Log.d(
+ TAG,
+ "onExecuteWrite() - address="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + " status="
+ + status);
}
if (!address.equals(mDevice.getAddress())) {
return;
diff --git a/framework/java/android/bluetooth/BluetoothGattServer.java b/framework/java/android/bluetooth/BluetoothGattServer.java
index 289b587..53b491e 100644
--- a/framework/java/android/bluetooth/BluetoothGattServer.java
+++ b/framework/java/android/bluetooth/BluetoothGattServer.java
@@ -357,7 +357,13 @@
@Override
public void onMtuChanged(String address, int mtu) {
if (DBG) {
- Log.d(TAG, "onMtuChanged() - " + "device=" + address + ", mtu=" + mtu);
+ Log.d(
+ TAG,
+ "onMtuChanged() - "
+ + "device="
+ + BluetoothUtils.toAnonymizedAddress(address)
+ + ", mtu="
+ + mtu);
}
BluetoothDevice device = mAdapter.getRemoteDevice(address);
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java
index 28b4e77..829ee2f 100644
--- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java
@@ -21,7 +21,9 @@
import static android.Manifest.permission.BLUETOOTH_SCAN;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresNoPermission;
@@ -40,6 +42,8 @@
import android.util.CloseGuard;
import android.util.Log;
+import com.android.bluetooth.flags.Flags;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -1205,6 +1209,52 @@
return defaultValue;
}
+ /**
+ * Gets the {@link BluetoothLeBroadcastMetadata} of a specified source added to this Broadcast
+ * Sink.
+ *
+ * <p>This method retrieves the {@link BluetoothLeBroadcastMetadata} associated with the
+ * specified source. The metadata is obtained from the {@link BluetoothLeBroadcastReceiveState}
+ * maintained by this Broadcast Sink. If no matching metadata is found, this method returns
+ * {@code null}.
+ *
+ * <p>The source's {@link BluetoothLeBroadcastMetadata} is initially set by {@link
+ * #addSource(BluetoothDevice, BluetoothLeBroadcastMetadata, boolean)} and can be updated with
+ * {@link #modifySource(BluetoothDevice, int, BluetoothLeBroadcastMetadata)}.
+ *
+ * @param sink Broadcast Sink device
+ * @param sourceId Broadcast source id. Valid range is [0, 0xFF] as defined in the Broadcast
+ * Audio Scan Service 1.0 specification (section 3.2).
+ * @return metadata {@link BluetoothLeBroadcastMetadata} associated with the specified source.
+ * @throws IllegalArgumentException if sourceID is not [0, 0xFF].
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_API_GET_LOCAL_METADATA)
+ @SystemApi
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED})
+ public @Nullable BluetoothLeBroadcastMetadata getSourceMetadata(
+ @NonNull BluetoothDevice sink, @IntRange(from = 0x00, to = 0xFF) int sourceId) {
+ log("getSourceMetadata()");
+ Objects.requireNonNull(sink, "sink cannot be null");
+ if (sourceId < 0x00 || sourceId > 0xFF) {
+ throw new IllegalArgumentException(
+ "sourceId " + sourceId + " does not fall between 0x00 and 0xFF");
+ }
+ final IBluetoothLeBroadcastAssistant service = getService();
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ } else if (mBluetoothAdapter.isEnabled()) {
+ try {
+ return service.getSourceMetadata(sink, sourceId, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ }
+ }
+ return null;
+ }
+
private static void log(@NonNull String msg) {
if (DBG) {
Log.d(TAG, msg);
diff --git a/framework/tests/bumble/OWNERS b/framework/tests/bumble/OWNERS
deleted file mode 100644
index 5bc200e..0000000
--- a/framework/tests/bumble/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 1099313
-# Project owners
-set noparent
-girardier@google.com
-charliebout@google.com
diff --git a/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt b/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt
index 9d42f3d..e658e8c 100644
--- a/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt
+++ b/framework/tests/bumble/src/android/bluetooth/DckL2capTest.kt
@@ -137,6 +137,7 @@
}
@Test
+ @VirtualOnly
fun testSend() {
Log.d(TAG, "testSend")
val remoteDevice =
@@ -189,6 +190,7 @@
}
@Test
+ @VirtualOnly
fun testReceive() {
Log.d(TAG, "testReceive: Connect L2CAP")
var bluetoothSocket: BluetoothSocket?
diff --git a/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java b/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java
index 3f728e4..506586b 100644
--- a/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/LeScanningTest.java
@@ -85,7 +85,8 @@
@Rule(order = 2)
public final EnableBluetoothRule mEnableBluetoothRule = new EnableBluetoothRule(false, true);
- private final Context mContext = ApplicationProvider.getApplicationContext();
+ private final Context mContext =
+ ApplicationProvider.getApplicationContext().createAttributionContext(TAG);
private final BluetoothManager mBluetoothManager =
mContext.getSystemService(BluetoothManager.class);
private final BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
@@ -354,6 +355,7 @@
}
@Test
+ @VirtualOnly
public void startBleScan_withServiceData() {
advertiseWithBumbleWithServiceData();
diff --git a/framework/tests/bumble/src/android/bluetooth/VirtualOnly.java b/framework/tests/bumble/src/android/bluetooth/VirtualOnly.java
new file mode 100644
index 0000000..77d7555
--- /dev/null
+++ b/framework/tests/bumble/src/android/bluetooth/VirtualOnly.java
@@ -0,0 +1,28 @@
+/*
+ * 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 android.bluetooth;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface VirtualOnly {
+ String value() default "";
+}
diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java
index 778fc23..cddee2a 100644
--- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostDualModeTest.java
@@ -49,6 +49,7 @@
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.PandoraDevice;
+import android.bluetooth.VirtualOnly;
import android.bluetooth.test_utils.EnableBluetoothRule;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -92,6 +93,7 @@
/** Test cases for {@link BluetoothHidHost}. */
@SuppressLint("MissingPermission")
@RunWith(AndroidJUnit4.class)
+@VirtualOnly
public class HidHostDualModeTest {
private static final String TAG = HidHostDualModeTest.class.getSimpleName();
private static final String BUMBLE_DEVICE_NAME = "Bumble";
diff --git a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java
index fde1a29..76eda63 100644
--- a/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/hid/HidHostTest.java
@@ -46,6 +46,7 @@
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.PandoraDevice;
+import android.bluetooth.VirtualOnly;
import android.bluetooth.cts.EnableBluetoothRule;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -91,6 +92,7 @@
/** Test cases for {@link BluetoothHidHost}. */
@RunWith(AndroidJUnit4.class)
+@VirtualOnly
public class HidHostTest {
private static final String TAG = HidHostTest.class.getSimpleName();
private static final Duration INTENT_TIMEOUT = Duration.ofSeconds(10);
diff --git a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java
index 27b0f10..2f6a56c 100644
--- a/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java
+++ b/framework/tests/bumble/src/android/bluetooth/service_discovery/LeAudioServiceDiscoveryTest.java
@@ -32,6 +32,7 @@
import android.bluetooth.BluetoothUuid;
import android.bluetooth.Host;
import android.bluetooth.PandoraDevice;
+import android.bluetooth.VirtualOnly;
import android.bluetooth.test_utils.EnableBluetoothRule;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -204,6 +205,7 @@
* Classic services
*/
@Test
+ @VirtualOnly
public void testServiceDiscoveryWithRandomAddr() {
registerIntentActions(
diff --git a/pandora/OWNERS b/pandora/OWNERS
index f45a253..14634f3 100644
--- a/pandora/OWNERS
+++ b/pandora/OWNERS
@@ -1,3 +1,2 @@
# Project owners
girardier@google.com
-charliebout@google.com
diff --git a/system/audio_bluetooth_hw/stream_apis.cc b/system/audio_bluetooth_hw/stream_apis.cc
index 7b96f5a..6854a61 100644
--- a/system/audio_bluetooth_hw/stream_apis.cc
+++ b/system/audio_bluetooth_hw/stream_apis.cc
@@ -775,6 +775,7 @@
out->frames_rendered_ = 0;
out->frames_presented_ = 0;
+ out->last_write_time_us_ = 0;
BluetoothStreamOut* out_ptr = out.release();
{
diff --git a/system/bta/Android.bp b/system/bta/Android.bp
index 4ffce69..812c482 100644
--- a/system/bta/Android.bp
+++ b/system/bta/Android.bp
@@ -154,7 +154,11 @@
"libcom.android.sysprop.bluetooth.wrapped",
"liblc3",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libcrypto",
],
generated_headers: [
@@ -651,12 +655,17 @@
"vc/vc.cc",
"vc/vc_test.cc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libbase",
+ "libbinder",
"libcrypto",
"liblog",
],
static_libs: [
+ "aics",
"bluetooth_flags_c_lib_for_test",
"libbluetooth-types",
"libbluetooth_crypto_toolbox",
diff --git a/system/bta/BUILD.gn b/system/bta/BUILD.gn
index b328715..928359a 100644
--- a/system/bta/BUILD.gn
+++ b/system/bta/BUILD.gn
@@ -145,6 +145,7 @@
"//bt/system/include",
"//bt/system/linux_include",
"//bt/system/bta",
+ "//bt/system/bta/aics/include",
"//bt/system/gd",
"//bt/system/stack/include",
"//bt/system/stack/btm",
@@ -173,6 +174,7 @@
"//bt/system/bta:install_audio_set_configurations_json",
"//bt/system/bta:install_audio_set_scenarios_bfbs",
"//bt/system/bta:install_audio_set_configurations_bfbs",
+ "//bt/system/bta/aics:aics",
"//bt/system:libbt-platform-protos-lite",
]
diff --git a/system/bta/aics/Android.bp b/system/bta/aics/Android.bp
new file mode 100644
index 0000000..33bd649
--- /dev/null
+++ b/system/bta/aics/Android.bp
@@ -0,0 +1,32 @@
+cc_library_headers {
+ name: "aics_headers",
+ export_include_dirs: ["include"],
+ 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"],
+ min_sdk_version: "33",
+}
+
+cc_library {
+ name: "aics",
+ defaults: ["fluoride_defaults"],
+ srcs: [
+ "aics.cc",
+ ],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libbluetooth_log",
+ "liblog",
+ ],
+ header_libs: ["aics_headers"],
+ export_header_lib_headers: ["aics_headers"],
+ host_supported: true,
+ visibility: ["//packages/modules/Bluetooth:__subpackages__"],
+ apex_available: ["com.android.btservices"],
+ min_sdk_version: "33",
+}
diff --git a/system/bta/aics/BUILD.gn b/system/bta/aics/BUILD.gn
new file mode 100644
index 0000000..5663e36
--- /dev/null
+++ b/system/bta/aics/BUILD.gn
@@ -0,0 +1,40 @@
+# 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.
+
+config("aics_defaults") {
+ include_dirs = [
+ "include",
+ ]
+ configs = [
+ "//bt/system:target_defaults",
+ "//bt/system/log:log_defaults",
+ ]
+}
+
+static_library("aics") {
+ sources = [
+ "aics.cc",
+ ]
+ configs += [
+ ":aics_defaults",
+ ]
+ # include_dirs = [
+ # "include",
+ # ]
+
+ # configs += [
+ # "//bt/system:target_defaults",
+ # "//bt/system/log:log_defaults",
+ # ]
+}
+
diff --git a/system/bta/aics/aics.cc b/system/bta/aics/aics.cc
new file mode 100644
index 0000000..5b5c088
--- /dev/null
+++ b/system/bta/aics/aics.cc
@@ -0,0 +1,32 @@
+// 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.
+
+#define LOG_TAG "aics"
+
+#include <aics/api.h>
+#include <bluetooth/log.h>
+
+namespace bluetooth::aics {
+
+bool isValidAudioInputMuteValue(uint8_t data) {
+ return data >= static_cast<uint8_t>(Mute::NOT_MUTED) &&
+ data <= static_cast<uint8_t>(Mute::DISABLED);
+}
+
+Mute parseMuteField(uint8_t data) {
+ log::assert_that(isValidAudioInputMuteValue(data), "Not a valid Mute Value");
+
+ return static_cast<Mute>(data);
+}
+
+} // namespace bluetooth::aics
diff --git a/system/bta/aics/include/aics/api.h b/system/bta/aics/include/aics/api.h
new file mode 100644
index 0000000..aba825d
--- /dev/null
+++ b/system/bta/aics/include/aics/api.h
@@ -0,0 +1,36 @@
+// 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.
+
+#pragma once
+
+#ifndef TARGET_FLOSS
+#include <bluetooth/constants/aics/Mute.h>
+#endif
+
+#include <cstdint>
+
+namespace bluetooth::aics {
+
+#ifndef TARGET_FLOSS
+using Mute = bluetooth::constants::aics::Mute;
+#else
+// TODO: b/376941621 Support the aidl generation in FLOSS
+enum class Mute : int8_t { NOT_MUTED = 0, MUTED = 1, DISABLED = 2 };
+#endif
+
+/** Check if the data is a correct Mute value */
+bool isValidAudioInputMuteValue(uint8_t data);
+
+/** Convert valid data into a Mute value. Abort if data is not valid */
+Mute parseMuteField(uint8_t data);
+} // namespace bluetooth::aics
diff --git a/system/bta/dm/bta_dm_device_search.cc b/system/bta/dm/bta_dm_device_search.cc
index a5428dc..76219c3 100644
--- a/system/bta/dm/bta_dm_device_search.cc
+++ b/system/bta/dm/bta_dm_device_search.cc
@@ -342,11 +342,12 @@
}
static void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) {
- BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed",
- base::StringPrintf("status:%s state:%s name:\"%s\"",
- hci_status_code_text(remote_name_msg.hci_status).c_str(),
- bta_dm_state_text(bta_dm_search_get_state()).c_str(),
- PRIVATE_NAME(remote_name_msg.bd_name)));
+ BTM_LogHistory(
+ kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed",
+ base::StringPrintf("status:%s state:%s name:\"%s\"",
+ hci_status_code_text(remote_name_msg.hci_status).c_str(),
+ bta_dm_state_text(bta_dm_search_get_state()).c_str(),
+ PRIVATE_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/include/bta_vc_api.h b/system/bta/include/bta_vc_api.h
index bba5b41..2eb33c2 100644
--- a/system/bta/include/bta_vc_api.h
+++ b/system/bta/include/bta_vc_api.h
@@ -65,8 +65,8 @@
virtual void GetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id) = 0;
virtual void SetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id,
std::string descr) = 0;
- virtual void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id,
- int8_t value) = 0;
+ virtual void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id,
+ int8_t gain_setting) = 0;
/* Set Gain Mode as per AIS */
virtual void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id,
bool auto_mode) = 0;
diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc
index 01c2856..6a3e3e8 100644
--- a/system/bta/le_audio/client.cc
+++ b/system/bta/le_audio/client.cc
@@ -867,7 +867,10 @@
BidirectionalPair<AudioContexts> remote_contexts) {
LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
- log::debug("configuration_context_type= {}", ToString(configuration_context_type));
+ log::debug(
+ "configuration_context_type= {}, remote sink contexts= {}, remote source contexts= {}",
+ ToString(configuration_context_type), ToString(remote_contexts.sink),
+ ToString(remote_contexts.source));
log::debug("");
if (configuration_context_type >= LeAudioContextType::RFU) {
@@ -4701,16 +4704,18 @@
continue;
}
+ // Use only available contexts
contexts_pair.get(dir) &= group_available_contexts;
+
+ // Check we we should add UNSPECIFIED as well in case not available context is also not
+ // supported
auto unavail_but_supported = (unavail_contexts & group->GetSupportedContexts(dir));
if (unavail_but_supported.none() &&
group_available_contexts.test(LeAudioContextType::UNSPECIFIED)) {
- log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED",
- ToString(unavail_contexts));
- /* All unavailable are also unsupported - replace with UNSPECIFIED if
- * available
- */
contexts_pair.get(dir).set(LeAudioContextType::UNSPECIFIED);
+
+ log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED -> {}",
+ ToString(unavail_contexts), ToString(contexts_pair.get(dir)));
} else {
log::debug("Some contexts are supported but currently unavailable: {}!",
ToString(unavail_but_supported));
@@ -4732,7 +4737,8 @@
std::tie(dir, other_dir, local_hal_state) = entry;
if (contexts_pair.get(dir).test(LeAudioContextType::UNSPECIFIED)) {
- /* Try to use the other direction context if not UNSPECIFIED and active
+ /* If this directions is streaming just UNSPECIFIED and if other direction is streaming some
+ * meaningfull context type, try to use the meaningful context type
*/
if (contexts_pair.get(dir) == AudioContexts(LeAudioContextType::UNSPECIFIED)) {
auto is_other_direction_streaming = (*local_hal_state == AudioState::STARTED) ||
@@ -4746,7 +4752,8 @@
contexts_pair.get(dir) = contexts_pair.get(other_dir);
}
} else {
- log::debug("Removing UNSPECIFIED from the remote sink context: {}",
+ log::debug("Removing UNSPECIFIED from the remote {} context: {}",
+ dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source",
ToString(contexts_pair.get(other_dir)));
contexts_pair.get(dir).unset(LeAudioContextType::UNSPECIFIED);
}
@@ -4794,14 +4801,23 @@
BidirectionalPair<AudioContexts> DirectionalRealignMetadataAudioContexts(
LeAudioDeviceGroup* group, int remote_direction) {
- auto remote_other_direction =
- (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink
- ? bluetooth::le_audio::types::kLeAudioDirectionSource
- : bluetooth::le_audio::types::kLeAudioDirectionSink);
- auto other_direction_hal =
- (remote_other_direction == bluetooth::le_audio::types::kLeAudioDirectionSource
- ? audio_receiver_state_
- : audio_sender_state_);
+ uint8_t remote_other_direction;
+ std::string remote_direction_str;
+ std::string remote_other_direction_str;
+ AudioState other_direction_hal;
+
+ if (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink) {
+ remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSource;
+ remote_direction_str = "Sink";
+ remote_other_direction_str = "Source";
+ other_direction_hal = audio_receiver_state_;
+ } else {
+ remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSink;
+ remote_direction_str = "Source";
+ remote_other_direction_str = "Sink";
+ other_direction_hal = audio_sender_state_;
+ }
+
auto is_streaming_other_direction = (other_direction_hal == AudioState::STARTED) ||
(other_direction_hal == AudioState::READY_TO_START);
auto is_releasing_for_reconfiguration =
@@ -4863,9 +4879,7 @@
ToString(local_metadata_context_types_.sink));
log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
- log::debug("remote_direction= {}",
- (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource ? "Source"
- : "Sink"));
+ log::debug("remote_direction= {}", remote_direction_str);
log::debug("is_streaming_other_direction= {}", is_streaming_other_direction ? "True" : "False");
log::debug("is_releasing_for_reconfiguration= {}",
is_releasing_for_reconfiguration ? "True" : "False");
diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc
index 05a2624..37367f0 100644
--- a/system/bta/le_audio/le_audio_client_test.cc
+++ b/system/bta/le_audio/le_audio_client_test.cc
@@ -10606,7 +10606,7 @@
Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
Mock::VerifyAndClearExpectations(mock_le_audio_sink_hal_client_);
- log::info("TESTPOING 4: Disable call so we could go back to MEDIA");
+ log::info("TESTPOINT 4: Disable call so we could go back to MEDIA");
// ---------------------------------------
// Suspend should stop the stream
EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(1);
diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc
index 48d09a3..cc9f843 100644
--- a/system/bta/le_audio/state_machine.cc
+++ b/system/bta/le_audio/state_machine.cc
@@ -2946,6 +2946,11 @@
return CIS_STILL_NEEDED;
}
+ ase->cis_state = CisState::DISCONNECTING;
+ if (bidirection_ase) {
+ bidirection_ase->cis_state = CisState::DISCONNECTING;
+ }
+
group->RemoveCisFromStreamIfNeeded(leAudioDevice, ase->cis_conn_hdl);
IsoManager::GetInstance()->DisconnectCis(ase->cis_conn_hdl, HCI_ERR_PEER_USER);
log_history_->AddLogHistory(kLogStateMachineTag, group->group_id_, leAudioDevice->address_,
diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc
index 84b997b..dc601a5 100644
--- a/system/bta/le_audio/state_machine_test.cc
+++ b/system/bta/le_audio/state_machine_test.cc
@@ -4920,6 +4920,54 @@
}
}
+TEST_F(StateMachineTest, testInjectReleasingStateWhenEnabling) {
+ const auto context_type = kContextTypeConversational;
+ const int leaudio_group_id = 4;
+ channel_count_ = kLeAudioCodecChannelCountSingleChannel;
+
+ // Prepare fake connected device group
+ auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
+ PrepareConfigureCodecHandler(group, 2);
+ PrepareConfigureQosHandler(group, 2);
+ PrepareEnableHandler(group, 0, true, false);
+
+ InjectInitialConfiguredNotification(group);
+
+ EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
+ EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
+ EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
+ EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
+ EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
+ EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
+
+ // Stub Establish Cis and Remove CIG
+ ON_CALL(*mock_iso_manager_, EstablishCis).WillByDefault(Return());
+ ON_CALL(*mock_iso_manager_, RemoveCig).WillByDefault(Return());
+
+ group->PrintDebugState();
+
+ // Start the configuration and stream Media content
+ ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
+ group, context_type,
+ {.sink = types::AudioContexts(context_type),
+ .source = types::AudioContexts(context_type)}));
+
+ testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
+
+ group->PrintDebugState();
+
+ log::info("Inject Release of all ASEs");
+
+ EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
+
+ // Stub DisconnectCis to trigger the issue.
+ ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
+
+ InjectReleaseAndIdleStateForAGroup(group, true, false);
+
+ testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
+}
+
MATCHER_P(dataPathIsEq, expected, "") { return arg.data_path_id == expected; }
TEST_F(StateMachineTest, testConfigureDataPathForHost) {
diff --git a/system/bta/vc/device.cc b/system/bta/vc/device.cc
index f4f016f..43f1e61 100644
--- a/system/bta/vc/device.cc
+++ b/system/bta/vc/device.cc
@@ -123,53 +123,61 @@
}
void VolumeControlDevice::set_audio_input_control_service_handles(const gatt::Service& service) {
- VolumeAudioInput input = VolumeAudioInput(service.handle);
+ uint16_t state_handle{0};
+ uint16_t state_ccc_handle{0};
+ uint16_t gain_setting_handle{0};
+ uint16_t type_handle{0};
+ uint16_t status_handle{0};
+ uint16_t status_ccc_handle{0};
+ uint16_t control_point_handle{0};
+ uint16_t description_handle{0};
+ uint16_t description_ccc_handle{0};
+ uint16_t description_writable{0};
+
for (const gatt::Characteristic& chrc : service.characteristics) {
if (chrc.uuid == kVolumeAudioInputStateUuid) {
- input.state_handle = chrc.value_handle;
- input.state_ccc_handle = find_ccc_handle(chrc.value_handle);
- log::debug("{}, input_state handle={:#x}, ccc {:#x}", address, input.state_handle,
- input.state_ccc_handle);
-
- } else if (chrc.uuid == kVolumeAudioInputGainSettingUuid) {
- input.gain_setting_handle = chrc.value_handle;
-
+ state_handle = chrc.value_handle;
+ state_ccc_handle = find_ccc_handle(chrc.value_handle);
+ log::debug("{} state_handle={:#x} ccc={:#x}", address, state_handle, state_ccc_handle);
+ } else if (chrc.uuid == kVolumeAudioInputGainSettingPropertiesUuid) {
+ gain_setting_handle = chrc.value_handle;
} else if (chrc.uuid == kVolumeAudioInputTypeUuid) {
- input.type_handle = chrc.value_handle;
-
+ type_handle = chrc.value_handle;
} else if (chrc.uuid == kVolumeAudioInputStatusUuid) {
- input.status_handle = chrc.value_handle;
- input.status_ccc_handle = find_ccc_handle(chrc.value_handle);
- log::debug("{}, input_status handle={:#x}, ccc {:#x}", address, input.status_handle,
- input.status_ccc_handle);
-
+ status_handle = chrc.value_handle;
+ status_ccc_handle = find_ccc_handle(chrc.value_handle);
+ log::debug("{} status_handle={:#x} ccc={:#x}", address, status_handle, status_ccc_handle);
} else if (chrc.uuid == kVolumeAudioInputControlPointUuid) {
- input.control_point_handle = chrc.value_handle;
-
+ control_point_handle = chrc.value_handle;
} else if (chrc.uuid == kVolumeAudioInputDescriptionUuid) {
- input.description_handle = chrc.value_handle;
- input.description_ccc_handle = find_ccc_handle(chrc.value_handle);
- input.description_writable = chrc.properties & GATT_CHAR_PROP_BIT_WRITE_NR;
- log::debug("{}, input_desc handle={:#x}, ccc {:#x}", address, input.description_handle,
- input.description_ccc_handle);
-
+ description_handle = chrc.value_handle;
+ description_ccc_handle = find_ccc_handle(chrc.value_handle);
+ description_writable = chrc.properties & GATT_CHAR_PROP_BIT_WRITE_NR;
+ log::debug("{} description_handle={:#x} ccc={:#x}", address, description_handle,
+ description_ccc_handle);
} else {
- log::warn("unknown characteristic={}", chrc.uuid);
+ log::info("found unexpected characteristic={}", chrc.uuid);
}
}
// Check if all mandatory attributes are present
- if (GATT_HANDLE_IS_VALID(input.state_handle) && GATT_HANDLE_IS_VALID(input.state_ccc_handle) &&
- GATT_HANDLE_IS_VALID(input.gain_setting_handle) && GATT_HANDLE_IS_VALID(input.type_handle) &&
- GATT_HANDLE_IS_VALID(input.status_handle) && GATT_HANDLE_IS_VALID(input.status_ccc_handle) &&
- GATT_HANDLE_IS_VALID(input.control_point_handle) &&
- GATT_HANDLE_IS_VALID(input.description_handle)
+ if (!GATT_HANDLE_IS_VALID(state_handle) || !GATT_HANDLE_IS_VALID(state_ccc_handle) ||
+ !GATT_HANDLE_IS_VALID(gain_setting_handle) || !GATT_HANDLE_IS_VALID(type_handle) ||
+ !GATT_HANDLE_IS_VALID(status_handle) || !GATT_HANDLE_IS_VALID(status_ccc_handle) ||
+ !GATT_HANDLE_IS_VALID(control_point_handle) || !GATT_HANDLE_IS_VALID(description_handle)
/* description_ccc_handle is optional */) {
- audio_inputs.Add(input);
- log::info("{}, input added id={:#x}", address, input.id);
- } else {
- log::warn("{}, ignoring input handle={:#x}", address, service.handle);
+ log::error(
+ "The remote device {} does not comply with AICS 1-0, some handles are invalid. "
+ "The aics service with handle {:#x} will be ignored",
+ address, service.handle);
+ return;
}
+ VolumeAudioInput input = VolumeAudioInput(
+ audio_inputs.Size(), service.handle, state_handle, state_ccc_handle, gain_setting_handle,
+ type_handle, status_handle, status_ccc_handle, control_point_handle, description_handle,
+ description_ccc_handle, description_writable);
+ audio_inputs.Add(input);
+ log::info("{}, input added id={:#x}", address, input.id);
}
void VolumeControlDevice::set_volume_offset_control_service_handles(const gatt::Service& service) {
diff --git a/system/bta/vc/devices.h b/system/bta/vc/devices.h
index 3e81072..8c0a573 100644
--- a/system/bta/vc/devices.h
+++ b/system/bta/vc/devices.h
@@ -156,7 +156,7 @@
/*
* This is used to track the pending GATT operation handles. Once the list is
* empty the device is assumed ready and connected. We are doing it because we
- * want to make sure all the required characteristics and descritors are
+ * want to make sure all the required characteristics and descriptors are
* available on server side.
*/
std::unordered_set<uint16_t> handles_pending;
diff --git a/system/bta/vc/devices_test.cc b/system/bta/vc/devices_test.cc
index d2f389a..fea281c 100644
--- a/system/bta/vc/devices_test.cc
+++ b/system/bta/vc/devices_test.cc
@@ -44,6 +44,7 @@
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::Mock;
+using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SaveArg;
using ::testing::SetArgPointee;
@@ -74,8 +75,8 @@
}
VolumeControlDevices* devices_ = nullptr;
- gatt::MockBtaGattInterface gatt_interface;
- gatt::MockBtaGattQueue gatt_queue;
+ NiceMock<gatt::MockBtaGattInterface> gatt_interface;
+ NiceMock<gatt::MockBtaGattQueue> gatt_queue;
};
TEST_F(VolumeControlDevicesTest, test_add) {
@@ -288,7 +289,7 @@
builder.AddService(0x0020, 0x002e, kVolumeAudioInputUuid, false);
builder.AddCharacteristic(0x0021, 0x0022, kVolumeAudioInputStateUuid, GATT_CHAR_PROP_BIT_READ);
builder.AddDescriptor(0x0023, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
- builder.AddCharacteristic(0x0024, 0x0025, kVolumeAudioInputGainSettingUuid,
+ builder.AddCharacteristic(0x0024, 0x0025, kVolumeAudioInputGainSettingPropertiesUuid,
GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0026, 0x0027, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0028, 0x0029, kVolumeAudioInputStatusUuid,
@@ -304,7 +305,7 @@
builder.AddCharacteristic(0x0041, 0x0042, kVolumeAudioInputStateUuid,
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
builder.AddDescriptor(0x0043, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
- builder.AddCharacteristic(0x0044, 0x0045, kVolumeAudioInputGainSettingUuid,
+ builder.AddCharacteristic(0x0044, 0x0045, kVolumeAudioInputGainSettingPropertiesUuid,
GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0046, 0x0047, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0048, 0x0049, kVolumeAudioInputStatusUuid,
@@ -361,9 +362,9 @@
}
VolumeControlDevice* device = nullptr;
- gatt::MockBtaGattInterface gatt_interface;
- gatt::MockBtaGattQueue gatt_queue;
- bluetooth::manager::MockBtmInterface btm_interface;
+ NiceMock<gatt::MockBtaGattInterface> gatt_interface;
+ NiceMock<gatt::MockBtaGattQueue> gatt_queue;
+ NiceMock<bluetooth::manager::MockBtmInterface> btm_interface;
std::list<gatt::Service> services;
};
@@ -387,7 +388,7 @@
builder.AddCharacteristic(0x000c, 0x000d, kVolumeAudioInputStateUuid,
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
- builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingUuid,
+ builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingPropertiesUuid,
GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0011, 0x0012, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0013, 0x0014, kVolumeAudioInputStatusUuid,
@@ -423,7 +424,7 @@
builder.AddCharacteristic(0x000c, 0x000d, kVolumeAudioInputStateUuid,
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
builder.AddDescriptor(0x000e, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
- builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingUuid,
+ builder.AddCharacteristic(0x000f, 0x0010, kVolumeAudioInputGainSettingPropertiesUuid,
GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0011, 0x0012, kVolumeAudioInputTypeUuid, GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0013, 0x0014, kVolumeAudioInputStatusUuid,
@@ -542,8 +543,8 @@
SetSampleDatabase1();
ASSERT_EQ((size_t)2, device->audio_offsets.Size());
ASSERT_EQ((size_t)2, device->audio_inputs.Size());
- VolumeAudioInput* input_1 = device->audio_inputs.FindById(1);
- VolumeAudioInput* input_2 = device->audio_inputs.FindById(2);
+ VolumeAudioInput* input_1 = device->audio_inputs.FindById(0);
+ VolumeAudioInput* input_2 = device->audio_inputs.FindById(1);
ASSERT_NE(nullptr, input_1);
ASSERT_NE(nullptr, input_2);
ASSERT_NE(input_1->service_handle, input_2->service_handle);
@@ -578,7 +579,7 @@
tGATT_IF gatt_if = 0x0001;
std::vector<uint8_t> register_for_notification_data({0x01, 0x00});
- std::map<uint16_t, uint16_t> expected_subscribtions{
+ std::map<uint16_t, uint16_t> expected_subscriptions{
{0x0011, 0x0012} /* volume control state */,
{0x0016, 0x0017} /* volume control flags */,
{0x0022, 0x0023} /* audio input state 1 */,
@@ -595,7 +596,7 @@
EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0011, _, _));
EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0016, _, _));
- for (auto const& handle_pair : expected_subscribtions) {
+ for (auto const& handle_pair : expected_subscriptions) {
EXPECT_CALL(gatt_queue, WriteDescriptor(_, handle_pair.second, register_for_notification_data,
GATT_WRITE, _, _));
EXPECT_CALL(gatt_interface, RegisterForNotifications(gatt_if, _, handle_pair.first));
@@ -856,7 +857,7 @@
uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
SetSampleDatabase1();
EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0022, read_cb, nullptr));
- device->GetExtAudioInState(1, read_cb, nullptr);
+ device->GetExtAudioInState(0, read_cb, nullptr);
}
TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_status) {
@@ -864,7 +865,7 @@
uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
SetSampleDatabase1();
EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0049, read_cb, nullptr));
- device->GetExtAudioInStatus(2, read_cb, nullptr);
+ device->GetExtAudioInStatus(1, read_cb, nullptr);
}
TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_gain_props) {
@@ -872,7 +873,7 @@
uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
SetSampleDatabase1();
EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x0025, read_cb, nullptr));
- device->GetExtAudioInGainProps(1, read_cb, nullptr);
+ device->GetExtAudioInGainProps(0, read_cb, nullptr);
}
TEST_F(VolumeControlDeviceTest, test_get_ext_audio_in_description) {
@@ -880,7 +881,7 @@
uint16_t /*len*/, uint8_t* /*value*/, void* /*data*/) {};
SetSampleDatabase1();
EXPECT_CALL(gatt_queue, ReadCharacteristic(_, 0x002e, read_cb, nullptr));
- device->GetExtAudioInDescription(1, read_cb, nullptr);
+ device->GetExtAudioInDescription(0, read_cb, nullptr);
}
TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description) {
@@ -889,7 +890,7 @@
std::vector<uint8_t> expected_data(descr.begin(), descr.end());
EXPECT_CALL(gatt_queue,
WriteCharacteristic(_, 0x004e, expected_data, GATT_WRITE_NO_RSP, nullptr, nullptr));
- device->SetExtAudioInDescription(2, descr);
+ device->SetExtAudioInDescription(1, descr);
}
TEST_F(VolumeControlDeviceTest, test_set_ext_audio_in_description_non_writable) {
@@ -897,34 +898,34 @@
std::string descr = "AUX";
std::vector<uint8_t> expected_data(descr.begin(), descr.end());
EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
- device->SetExtAudioInDescription(1, descr);
+ device->SetExtAudioInDescription(0, descr);
}
TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation) {
GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
SetSampleDatabase1();
- VolumeAudioInput* input = device->audio_inputs.FindById(2);
+ VolumeAudioInput* input = device->audio_inputs.FindById(1);
ASSERT_NE(nullptr, input);
input->change_counter = 0x11;
std::vector<uint8_t> expected_data({0x0c, 0x11});
EXPECT_CALL(gatt_queue,
WriteCharacteristic(_, 0x004c, expected_data, GATT_WRITE, write_cb, nullptr));
- device->ExtAudioInControlPointOperation(2, 0x0c, nullptr, write_cb, nullptr);
+ device->ExtAudioInControlPointOperation(1, 0x0c, nullptr, write_cb, nullptr);
}
TEST_F(VolumeControlDeviceTest, test_ext_audio_in_control_point_operation_arg) {
GATT_WRITE_OP_CB write_cb = [](uint16_t /*conn_id*/, tGATT_STATUS /*status*/, uint16_t /*handle*/,
uint16_t /*len*/, const uint8_t* /*value*/, void* /*data*/) {};
SetSampleDatabase1();
- VolumeAudioInput* input = device->audio_inputs.FindById(2);
+ VolumeAudioInput* input = device->audio_inputs.FindById(1);
ASSERT_NE(nullptr, input);
input->change_counter = 0x12;
std::vector<uint8_t> expected_data({0x0d, 0x12, 0x01, 0x02, 0x03, 0x04});
std::vector<uint8_t> arg({0x01, 0x02, 0x03, 0x04});
EXPECT_CALL(gatt_queue,
WriteCharacteristic(_, 0x004c, expected_data, GATT_WRITE, write_cb, nullptr));
- device->ExtAudioInControlPointOperation(2, 0x0d, &arg, write_cb, nullptr);
+ device->ExtAudioInControlPointOperation(1, 0x0d, &arg, write_cb, nullptr);
}
} // namespace internal
diff --git a/system/bta/vc/types.h b/system/bta/vc/types.h
index f1f35a1..65d8355 100644
--- a/system/bta/vc/types.h
+++ b/system/bta/vc/types.h
@@ -17,6 +17,7 @@
#pragma once
+#include <aics/api.h>
#include <hardware/bt_vc.h>
#include <algorithm>
@@ -53,24 +54,24 @@
static constexpr uint8_t kVolumeInputControlPointOpcodeSetManualGainMode = 0x04;
static constexpr uint8_t kVolumeInputControlPointOpcodeSetAutoGainMode = 0x05;
-static const Uuid kVolumeControlUuid = Uuid::From16Bit(0x1844);
-static const Uuid kVolumeControlStateUuid = Uuid::From16Bit(0x2B7D);
-static const Uuid kVolumeControlPointUuid = Uuid::From16Bit(0x2B7E);
-static const Uuid kVolumeFlagsUuid = Uuid::From16Bit(0x2B7F);
+static const Uuid kVolumeControlUuid = Uuid::From16Bit(0x1844);
+static const Uuid kVolumeControlStateUuid = Uuid::From16Bit(0x2B7D);
+static const Uuid kVolumeControlPointUuid = Uuid::From16Bit(0x2B7E);
+static const Uuid kVolumeFlagsUuid = Uuid::From16Bit(0x2B7F);
-static const Uuid kVolumeOffsetUuid = Uuid::From16Bit(0x1845);
-static const Uuid kVolumeOffsetStateUuid = Uuid::From16Bit(0x2B80);
-static const Uuid kVolumeOffsetLocationUuid = Uuid::From16Bit(0x2B81);
-static const Uuid kVolumeOffsetControlPointUuid = Uuid::From16Bit(0x2B82);
-static const Uuid kVolumeOffsetOutputDescriptionUuid = Uuid::From16Bit(0x2B83);
+static const Uuid kVolumeOffsetUuid = Uuid::From16Bit(0x1845);
+static const Uuid kVolumeOffsetStateUuid = Uuid::From16Bit(0x2B80);
+static const Uuid kVolumeOffsetLocationUuid = Uuid::From16Bit(0x2B81);
+static const Uuid kVolumeOffsetControlPointUuid = Uuid::From16Bit(0x2B82);
+static const Uuid kVolumeOffsetOutputDescriptionUuid = Uuid::From16Bit(0x2B83);
-static const Uuid kVolumeAudioInputUuid = Uuid::From16Bit(0x1843);
-static const Uuid kVolumeAudioInputStateUuid = Uuid::From16Bit(0x2B77);
-static const Uuid kVolumeAudioInputGainSettingUuid = Uuid::From16Bit(0x2B78);
-static const Uuid kVolumeAudioInputTypeUuid = Uuid::From16Bit(0x2B79);
-static const Uuid kVolumeAudioInputStatusUuid = Uuid::From16Bit(0x2B7A);
-static const Uuid kVolumeAudioInputControlPointUuid = Uuid::From16Bit(0x2B7B);
-static const Uuid kVolumeAudioInputDescriptionUuid = Uuid::From16Bit(0x2B7C);
+static const Uuid kVolumeAudioInputUuid = Uuid::From16Bit(0x1843);
+static const Uuid kVolumeAudioInputStateUuid = Uuid::From16Bit(0x2B77);
+static const Uuid kVolumeAudioInputGainSettingPropertiesUuid = Uuid::From16Bit(0x2B78);
+static const Uuid kVolumeAudioInputTypeUuid = Uuid::From16Bit(0x2B79);
+static const Uuid kVolumeAudioInputStatusUuid = Uuid::From16Bit(0x2B7A);
+static const Uuid kVolumeAudioInputControlPointUuid = Uuid::From16Bit(0x2B7B);
+static const Uuid kVolumeAudioInputDescriptionUuid = Uuid::From16Bit(0x2B7C);
/* clang-format on */
@@ -127,64 +128,58 @@
};
struct GainSettings {
- uint8_t unit;
- int8_t min;
- int8_t max;
+ uint8_t unit = 0;
+ int8_t min = 0;
+ int8_t max = 0;
- GainSettings() : unit(0), min(0), max(0) {}
+ GainSettings() {}
};
struct VolumeAudioInput {
- uint8_t id;
- bool mute;
- int8_t gain_value;
- VolumeInputStatus status;
- VolumeInputType type;
- uint8_t change_counter;
- uint8_t mode;
- std::string description;
- uint16_t service_handle;
- uint16_t state_handle;
- uint16_t state_ccc_handle;
- uint16_t gain_setting_handle;
- uint16_t type_handle;
- uint16_t status_handle;
- uint16_t status_ccc_handle;
- uint16_t control_point_handle;
- uint16_t description_handle;
- uint16_t description_ccc_handle;
- bool description_writable;
- struct GainSettings gain_settings;
+ /* const */ uint8_t id;
+ Mute mute = bluetooth::aics::Mute::DISABLED;
+ int8_t gain_setting = 0;
+ VolumeInputStatus status = VolumeInputStatus::Inactive;
+ VolumeInputType type = VolumeInputType::Unspecified;
+ uint8_t change_counter = 0;
+ uint8_t mode = 0;
+ std::string description = "";
+ /* const */ uint16_t service_handle;
+ /* const */ uint16_t state_handle;
+ /* const */ uint16_t state_ccc_handle;
+ /* const */ uint16_t gain_setting_handle;
+ /* const */ uint16_t type_handle;
+ /* const */ uint16_t status_handle;
+ /* const */ uint16_t status_ccc_handle;
+ /* const */ uint16_t control_point_handle;
+ /* const */ uint16_t description_handle;
+ /* const */ uint16_t description_ccc_handle;
+ /* const */ bool description_writable;
+ struct GainSettings gain_settings = GainSettings();
- explicit VolumeAudioInput(uint16_t service_handle)
- : id(0),
- mute(false),
- gain_value(0),
- status(VolumeInputStatus::Inactive),
- type(VolumeInputType::Unspecified),
- change_counter(0),
- mode(0),
- description(""),
+ explicit VolumeAudioInput(uint8_t id, uint16_t service_handle, uint16_t state_handle,
+ uint16_t state_ccc_handle, uint16_t gain_setting_handle,
+ uint16_t type_handle, uint16_t status_handle,
+ uint16_t status_ccc_handle, uint16_t control_point_handle,
+ uint16_t description_handle, uint16_t description_ccc_handle,
+ bool description_writable)
+ : id(id),
service_handle(service_handle),
- state_handle(0),
- state_ccc_handle(0),
- gain_setting_handle(0),
- type_handle(0),
- status_handle(0),
- status_ccc_handle(0),
- control_point_handle(0),
- description_handle(0),
- description_ccc_handle(0),
- description_writable(false),
- gain_settings(GainSettings()) {}
+ state_handle(state_handle),
+ state_ccc_handle(state_ccc_handle),
+ gain_setting_handle(gain_setting_handle),
+ type_handle(type_handle),
+ status_handle(status_handle),
+ status_ccc_handle(status_ccc_handle),
+ control_point_handle(control_point_handle),
+ description_handle(description_handle),
+ description_ccc_handle(description_ccc_handle),
+ description_writable(description_writable) {}
};
class VolumeAudioInputs {
public:
- void Add(VolumeAudioInput input) {
- input.id = (uint8_t)Size() + 1;
- volume_audio_inputs.push_back(input);
- }
+ void Add(VolumeAudioInput input) { volume_audio_inputs.push_back(input); }
VolumeAudioInput* FindByType(VolumeInputType type) {
auto iter = std::find_if(volume_audio_inputs.begin(), volume_audio_inputs.end(),
diff --git a/system/bta/vc/vc.cc b/system/bta/vc/vc.cc
index 2c415a5..9c89b98 100644
--- a/system/bta/vc/vc.cc
+++ b/system/bta/vc/vc.cc
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#include <aics/api.h>
#include <base/functional/bind.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
@@ -580,24 +581,31 @@
}
uint8_t* pp = value;
- STREAM_TO_INT8(input->gain_value, pp);
- STREAM_TO_UINT8(input->mute, pp);
+ STREAM_TO_INT8(input->gain_setting, pp);
+ uint8_t mute;
+ STREAM_TO_UINT8(mute, pp);
+ if (!bluetooth::aics::isValidAudioInputMuteValue(mute)) {
+ bluetooth::log::error("{} Invalid mute value: {:#x}", device->address, mute);
+ return;
+ }
+ input->mute = bluetooth::aics::parseMuteField(mute);
+
STREAM_TO_UINT8(input->mode, pp);
STREAM_TO_UINT8(input->change_counter, pp);
bluetooth::log::verbose("{}, data:{}", device->address, base::HexEncode(value, len));
bluetooth::log::info(
- "{} id={:#x}gain_value {:#x}, mute: {:#x}, mode: {:#x}, "
+ "{} id={:#x}gain_setting {:#x}, mute: {:#x}, mode: {:#x}, "
"change_counter: {}",
- device->address, input->id, input->gain_value, input->mute, input->mode,
+ device->address, input->id, input->gain_setting, mute, input->mode,
input->change_counter);
if (!device->device_ready) {
return;
}
- callbacks_->OnExtAudioInStateChanged(device->address, input->id, input->gain_value, input->mode,
- input->mute);
+ callbacks_->OnExtAudioInStateChanged(device->address, input->id, input->gain_setting,
+ input->mute, input->mode);
}
void OnExtAudioInTypeChanged(VolumeControlDevice* device, VolumeAudioInput* input, uint16_t len,
@@ -1284,9 +1292,9 @@
device->SetExtAudioInDescription(ext_input_id, descr);
}
- void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id,
- int8_t value) override {
- std::vector<uint8_t> arg({(uint8_t)value});
+ void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id,
+ int8_t gain_setting) override {
+ std::vector<uint8_t> arg({(uint8_t)gain_setting});
ext_audio_in_control_point_helper(address, ext_input_id, kVolumeInputControlPointOpcodeSetGain,
&arg);
}
@@ -1503,7 +1511,7 @@
if (position + len >= total_len) {
bluetooth::log::warn(
- "Multi read was too long, value truncated conn_id: {:#x} handle: {:#x}, possition: "
+ "Multi read was too long, value truncated conn_id: {:#x} handle: {:#x}, position: "
"{:#x}, len: {:#x}, total_len: {:#x}, data: {}",
conn_id, hdl, position, len, total_len, base::HexEncode(value, total_len));
break;
diff --git a/system/bta/vc/vc_test.cc b/system/bta/vc/vc_test.cc
index b0f203b..8b69fb3 100644
--- a/system/bta/vc/vc_test.cc
+++ b/system/bta/vc/vc_test.cc
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#include <aics/api.h>
#include <base/functional/bind.h>
#include <com_android_bluetooth_flags.h>
#include <gmock/gmock.h>
@@ -48,6 +49,8 @@
bool on_main_loop = false;
};
+using ::testing::NiceMock;
+
namespace bluetooth {
namespace vc {
namespace internal {
@@ -56,6 +59,7 @@
using base::Bind;
using base::Unretained;
+using bluetooth::aics::Mute;
using bluetooth::vc::ConnectionState;
using bluetooth::vc::VolumeControlCallbacks;
@@ -101,8 +105,8 @@
MOCK_METHOD((void), OnExtAudioOutDescriptionChanged,
(const RawAddress& address, uint8_t ext_output_id, std::string descr), (override));
MOCK_METHOD((void), OnExtAudioInStateChanged,
- (const RawAddress& address, uint8_t ext_input_id, int8_t gain_val,
- uint8_t gain_mode_auto, bool mute),
+ (const RawAddress& address, uint8_t ext_input_id, int8_t gain_setting, Mute mute,
+ uint8_t gain_mode_auto),
(override));
MOCK_METHOD((void), OnExtAudioInStatusChanged,
(const RawAddress& address, uint8_t ext_input_id, VolumeInputStatus status),
@@ -152,7 +156,7 @@
builder.AddCharacteristic(0x0031, 0x0032, kVolumeAudioInputStateUuid,
GATT_CHAR_PROP_BIT_READ);
builder.AddDescriptor(0x0033, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
- builder.AddCharacteristic(0x0034, 0x0035, kVolumeAudioInputGainSettingUuid,
+ builder.AddCharacteristic(0x0034, 0x0035, kVolumeAudioInputGainSettingPropertiesUuid,
GATT_CHAR_PROP_BIT_READ);
builder.AddCharacteristic(0x0036, 0x0037, kVolumeAudioInputTypeUuid,
GATT_CHAR_PROP_BIT_READ);
@@ -171,7 +175,7 @@
GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY);
builder.AddDescriptor(0x0053, Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG));
if (!aics_broken) {
- builder.AddCharacteristic(0x0054, 0x0055, kVolumeAudioInputGainSettingUuid,
+ builder.AddCharacteristic(0x0054, 0x0055, kVolumeAudioInputGainSettingPropertiesUuid,
GATT_CHAR_PROP_BIT_READ);
}
builder.AddCharacteristic(0x0056, 0x0057, kVolumeAudioInputTypeUuid,
@@ -315,7 +319,7 @@
std::vector<uint8_t> value;
auto add_element = [&](uint8_t data[], uint8_t len) -> void {
- // LE order, 2 octects
+ // LE order, 2 octets
value.push_back(len);
value.push_back(0x00);
@@ -434,7 +438,6 @@
MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
gatt::SetMockBtaGattInterface(&gatt_interface);
gatt::SetMockBtaGattQueue(&gatt_queue);
- callbacks.reset(new MockVolumeControlCallbacks());
reset_mock_function_count_map();
ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(true)));
@@ -535,7 +538,6 @@
void TearDown(void) override {
com::android::bluetooth::flags::provider_->reset_flags();
services_map.clear();
- callbacks.reset();
gatt::SetMockBtaGattQueue(nullptr);
gatt::SetMockBtaGattInterface(nullptr);
bluetooth::manager::SetMockBtmInterface(nullptr);
@@ -546,7 +548,7 @@
BtaAppRegisterCallback app_register_callback;
EXPECT_CALL(gatt_interface, AppRegister(_, _, _))
.WillOnce(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
- VolumeControl::Initialize(callbacks.get(), base::DoNothing());
+ VolumeControl::Initialize(&callbacks, base::DoNothing());
ASSERT_TRUE(gatt_callback);
ASSERT_TRUE(app_register_callback);
app_register_callback.Run(gatt_if, GATT_SUCCESS);
@@ -738,11 +740,12 @@
set_sample_database(conn_id, true, false, true, false, true, false);
}
- std::unique_ptr<MockVolumeControlCallbacks> callbacks;
- bluetooth::manager::MockBtmInterface btm_interface;
+ NiceMock<MockVolumeControlCallbacks> callbacks;
+ NiceMock<bluetooth::manager::MockBtmInterface> btm_interface;
MockCsisClient mock_csis_client_module_;
- gatt::MockBtaGattInterface gatt_interface;
- gatt::MockBtaGattQueue gatt_queue;
+ NiceMock<gatt::MockBtaGattInterface> gatt_interface;
+ NiceMock<gatt::MockBtaGattQueue> gatt_queue;
+
tBTA_GATTC_CBACK* gatt_callback;
const uint8_t gatt_if = 0xff;
std::map<uint16_t, std::list<gatt::Service>> services_map;
@@ -756,7 +759,7 @@
EXPECT_CALL(gatt_interface, AppRegister(_, _, _))
.WillOnce(DoAll(SaveArg<0>(&gatt_callback), SaveArg<1>(&app_register_callback)));
VolumeControl::Initialize(
- callbacks.get(),
+ &callbacks,
base::Bind([](bool* init_cb_called) { *init_cb_called = true; }, &init_cb_called));
ASSERT_TRUE(gatt_callback);
ASSERT_TRUE(app_register_callback);
@@ -768,15 +771,15 @@
}
TEST_F(VolumeControlTest, test_initialize_twice) {
- VolumeControl::Initialize(callbacks.get(), base::DoNothing());
+ VolumeControl::Initialize(&callbacks, base::DoNothing());
VolumeControl* volume_control_p = VolumeControl::Get();
- VolumeControl::Initialize(callbacks.get(), base::DoNothing());
+ VolumeControl::Initialize(&callbacks, base::DoNothing());
ASSERT_EQ(volume_control_p, VolumeControl::Get());
VolumeControl::CleanUp();
}
TEST_F(VolumeControlTest, test_cleanup_initialized) {
- VolumeControl::Initialize(callbacks.get(), base::DoNothing());
+ VolumeControl::Initialize(&callbacks, base::DoNothing());
VolumeControl::CleanUp();
ASSERT_FALSE(VolumeControl::IsVolumeControlRunning());
}
@@ -805,18 +808,18 @@
TestConnect(test_address);
GetConnectedEvent(test_address, conn_id);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1);
TestRemove(test_address, conn_id);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(1);
ON_CALL(btm_interface, IsLinkKeyKnown(_, _)).WillByDefault(DoAll(Return(false)));
VolumeControl::Get()->Connect(test_address);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -828,15 +831,15 @@
SetSampleDatabaseVOCS(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0);
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0);
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0);
GetConnectedEvent(test_address, 1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
// Remote disconnects in the middle of the service discovery
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
GetDisconnectedEvent(test_address, 1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
// This time let the service discovery pass
ON_CALL(gatt_interface, ServiceSearchRequest(_, _))
@@ -847,19 +850,19 @@
}));
// Remote is being connected by another GATT client
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _));
GetConnectedEvent(test_address, 1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
// Request connect when the remote was already connected by another service
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
VolumeControl::Get()->Connect(test_address);
// The GetConnectedEvent(test_address, 1); should not be triggered here, since
// GATT implementation will not send this event for the already connected
// device
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -871,14 +874,14 @@
TestAddFromStorage(address);
Mock::VerifyAndClearExpectations(&gatt_interface);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)).Times(1);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address)).Times(1);
TestConnect(address);
EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, _)).Times(0);
EXPECT_CALL(gatt_interface, Open(gatt_if, address, BTM_BLE_DIRECT_CONNECTION, true)).Times(1);
GetConnectedEvent(address, 1, GATT_ERROR);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
Mock::VerifyAndClearExpectations(&gatt_interface);
TestAppUnregister();
}
@@ -890,12 +893,12 @@
SetSampleDatabaseVOCS(1);
TestAppRegister();
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, address)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, address)).Times(0);
TestConnect(address);
// Disconnect not connected device - upper layer times out and needs a
// disconnection event to leave the transient Connecting state
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address));
EXPECT_CALL(gatt_interface, CancelOpen(gatt_if, address, false)).Times(0);
TestDisconnect(address, 0);
@@ -909,16 +912,16 @@
GetSearchCompleteEvent(conn_id);
}
}));
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, address));
- EXPECT_CALL(*callbacks, OnDeviceAvailable(address, 2, _));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(address, 2, _));
GetConnectedEvent(address, 1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
// Make sure that the upper layer gets the disconnection event even if not
// connecting actively anymore due to the mentioned time-out mechanism.
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, address));
GetDisconnectedEvent(address, 1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -932,7 +935,7 @@
const RawAddress test_address = GetTestAddress(0);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
TestRemove(test_address, 0);
TestAppUnregister();
}
@@ -942,7 +945,7 @@
TestAppRegister();
TestConnect(test_address);
GetConnectedEvent(test_address, 1);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
TestDisconnect(test_address, 1);
TestAppUnregister();
}
@@ -951,7 +954,7 @@
const RawAddress test_address = GetTestAddress(0);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
TestDisconnect(test_address, 0);
TestAppUnregister();
}
@@ -961,7 +964,7 @@
TestAppRegister();
TestConnect(test_address);
GetConnectedEvent(test_address, 1);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
TestDisconnect(test_address, 1);
TestAppUnregister();
}
@@ -971,7 +974,7 @@
TestAppRegister();
TestConnect(test_address);
GetConnectedEvent(test_address, 1);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
GetDisconnectedEvent(test_address, 1);
TestAppUnregister();
}
@@ -982,7 +985,7 @@
TestAddFromStorage(test_address);
GetConnectedEvent(test_address, 1);
// autoconnect - don't indicate disconnection
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0);
GetDisconnectedEvent(test_address, 1);
TestAppUnregister();
}
@@ -997,7 +1000,7 @@
.WillByDefault(Return(tBTM_STATUS::BTM_ERR_KEY_MISSING));
// autoconnect - don't indicate disconnection
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0);
EXPECT_CALL(gatt_interface, Close(1));
GetConnectedEvent(test_address, 1);
Mock::VerifyAndClearExpectations(&btm_interface);
@@ -1010,7 +1013,7 @@
TestAddFromStorage(test_address);
SetEncryptionResult(test_address, false);
// autoconnect - don't indicate disconnection
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address)).Times(0);
GetConnectedEvent(test_address, 1);
Mock::VerifyAndClearExpectations(&btm_interface);
SetEncryptionResult(test_address, true);
@@ -1029,14 +1032,14 @@
ON_CALL(btm_interface, SetEncryption(test_address, _, _, _, _))
.WillByDefault(Return(tBTM_STATUS::BTM_SUCCESS));
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(0);
uint16_t conn_id = 1;
GetConnectedEvent(test_address, conn_id);
GetSearchCompleteEvent(conn_id);
Mock::VerifyAndClearExpectations(&btm_interface);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1);
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address)).Times(1);
ON_CALL(btm_interface, BTM_IsEncrypted(test_address, _)).WillByDefault(DoAll(Return(true)));
EXPECT_CALL(gatt_interface, ServiceSearchRequest(_, _));
@@ -1044,7 +1047,7 @@
GetEncryptionCompleteEvt(test_address);
GetSearchCompleteEvent(conn_id);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
Mock::VerifyAndClearExpectations(&gatt_interface);
TestAppUnregister();
@@ -1055,11 +1058,11 @@
SetSampleDatabaseVCS(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, _, _));
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, _, _));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
GetConnectedEvent(test_address, 1);
GetSearchCompleteEvent(1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -1068,11 +1071,11 @@
SetSampleDatabaseNoVCS(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
GetConnectedEvent(test_address, 1);
GetSearchCompleteEvent(1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -1081,10 +1084,10 @@
SetSampleDatabaseVCSBroken(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
GetConnectedEvent(test_address, 1);
GetSearchCompleteEvent(1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -1110,7 +1113,7 @@
TEST_F(VolumeControlTest, test_read_vcs_volume_state) {
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _, true)).Times(1);
+ EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, _, _, _, true)).Times(1);
std::vector<uint16_t> handles({0x0021});
TestReadCharacteristic(test_address, 1, handles);
}
@@ -1123,29 +1126,29 @@
TEST_F(VolumeControlTest, test_read_vocs_volume_offset) {
com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false);
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
std::vector<uint16_t> handles({0x0072, 0x0082});
TestReadCharacteristic(test_address, 1, handles);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
}
TEST_F(VolumeControlTest, test_read_vocs_volume_offset_multi) {
com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true);
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
std::vector<uint16_t> handles({0x0072, 0x0082});
TestReadCharacteristic(test_address, 1, handles);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
}
TEST_F(VolumeControlTest, test_read_vocs_offset_location) {
@@ -1153,15 +1156,15 @@
const RawAddress test_address = GetTestAddress(0);
// It is called twice because after connect read is done once and second read is coming from the
// test.
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
std::vector<uint16_t> handles({0x0075, 0x0085});
TestReadCharacteristic(test_address, 1, handles);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
}
TEST_F(VolumeControlTest, test_read_vocs_offset_location_multi) {
@@ -1169,26 +1172,26 @@
const RawAddress test_address = GetTestAddress(0);
// It is called twice because after connect read is done once and second read is coming from the
// test.
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
std::vector<uint16_t> handles({0x0075, 0x0085});
TestReadCharacteristic(test_address, 1, handles);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
}
TEST_F(VolumeControlTest, test_read_vocs_output_description) {
com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(false);
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
std::vector<uint16_t> handles({0x0079, 0x008a});
TestReadCharacteristic(test_address, 1, handles);
}
@@ -1196,12 +1199,12 @@
TEST_F(VolumeControlTest, test_read_vocs_output_description_multi) {
com::android::bluetooth::flags::provider_->le_ase_read_multiple_variable(true);
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 1, _)).Times(1);
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, _)).Times(1);
std::vector<uint16_t> handles({0x0079, 0x008a});
TestReadCharacteristic(test_address, 1, handles);
}
@@ -1211,11 +1214,11 @@
SetSampleDatabaseVOCS(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 2, _));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 2, _));
GetConnectedEvent(test_address, 1);
GetSearchCompleteEvent(1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -1224,11 +1227,11 @@
SetSampleDatabaseVCS(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 0, _));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 0, _));
GetConnectedEvent(test_address, 1);
GetSearchCompleteEvent(1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
@@ -1237,17 +1240,17 @@
SetSampleDatabaseVOCSBroken(1);
TestAppRegister();
TestConnect(test_address);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
- EXPECT_CALL(*callbacks, OnDeviceAvailable(test_address, 1, _));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::CONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnDeviceAvailable(test_address, 1, _));
GetConnectedEvent(test_address, 1);
GetSearchCompleteEvent(1);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
TestAppUnregister();
}
TEST_F(VolumeControlTest, test_read_vcs_database_out_of_sync) {
const RawAddress test_address = GetTestAddress(0);
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _, true));
+ EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, _, _, _, true));
std::vector<uint16_t> handles({0x0021});
uint16_t conn_id = 1;
@@ -1320,26 +1323,39 @@
TEST_F(VolumeControlCallbackTest, test_volume_state_changed_stress) {
std::vector<uint8_t> value({0x03, 0x01, 0x02});
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, 0x03, true, _, true));
+ EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, 0x03, true, _, true));
GetNotificationEvent(0x0021, value);
}
TEST_F(VolumeControlCallbackTest, test_volume_state_changed_malformed) {
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address, _, _, _, _)).Times(0);
+ EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address, _, _, _, _)).Times(0);
std::vector<uint8_t> too_short({0x03, 0x01});
GetNotificationEvent(0x0021, too_short);
std::vector<uint8_t> too_long({0x03, 0x01, 0x02, 0x03});
GetNotificationEvent(0x0021, too_long);
}
-TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed) {
- std::vector<uint8_t> value({0x03, 0x01, 0x02, 0x04});
- EXPECT_CALL(*callbacks, OnExtAudioInStateChanged(test_address, 1, 0x03, 0x02, true));
+TEST_F(VolumeControlCallbackTest, audio_input_state_changed__invalid_mute__is_rejected) {
+ uint8_t invalid_mute = 0x03;
+ std::vector<uint8_t> value({0x03, invalid_mute, 0x02, 0x04});
+ EXPECT_CALL(callbacks, OnExtAudioInStateChanged(_, _, _, _, _)).Times(0);
+ GetNotificationEvent(0x0032, value);
+}
+
+TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__muted) {
+ std::vector<uint8_t> value({0x03, (uint8_t)Mute::MUTED, 0x02, 0x04});
+ EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, Mute::MUTED, 0x02));
+ GetNotificationEvent(0x0032, value);
+}
+
+TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed__disabled) {
+ std::vector<uint8_t> value({0x03, (uint8_t)Mute::DISABLED, 0x02, 0x04});
+ EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, 0x03, Mute::DISABLED, 0x02));
GetNotificationEvent(0x0032, value);
}
TEST_F(VolumeControlCallbackTest, test_audio_input_state_changed_malformed) {
- EXPECT_CALL(*callbacks, OnExtAudioInStateChanged(test_address, 1, _, _, _)).Times(0);
+ EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, _, _, _, _)).Times(0);
std::vector<uint8_t> too_short({0x03, 0x01, 0x02});
GetNotificationEvent(0x0032, too_short);
std::vector<uint8_t> too_long({0x03, 0x01, 0x02, 0x04, 0x05});
@@ -1348,12 +1364,12 @@
TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed) {
std::vector<uint8_t> value({0x03, 0x01, 0x02});
- EXPECT_CALL(*callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x03, 0x01, 0x02));
+ EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, _, 0x03, 0x01, 0x02));
GetNotificationEvent(0x0055, value);
}
TEST_F(VolumeControlCallbackTest, test_audio_gain_props_changed_malformed) {
- EXPECT_CALL(*callbacks, OnExtAudioInGainPropsChanged(test_address, 2, _, _, _)).Times(0);
+ EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, _, _, _, _)).Times(0);
std::vector<uint8_t> too_short({0x03, 0x01});
GetNotificationEvent(0x0055, too_short);
std::vector<uint8_t> too_long({0x03, 0x01, 0x02, 0x03});
@@ -1362,13 +1378,13 @@
TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed) {
std::vector<uint8_t> value({static_cast<uint8_t>(bluetooth::vc::VolumeInputStatus::Inactive)});
- EXPECT_CALL(*callbacks, OnExtAudioInStatusChanged(test_address, 1,
- bluetooth::vc::VolumeInputStatus::Inactive));
+ EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, _,
+ bluetooth::vc::VolumeInputStatus::Inactive));
GetNotificationEvent(0x0039, value);
}
TEST_F(VolumeControlCallbackTest, test_audio_input_status_changed_malformed) {
- EXPECT_CALL(*callbacks, OnExtAudioInStatusChanged(test_address, 1, _)).Times(0);
+ EXPECT_CALL(callbacks, OnExtAudioInStatusChanged(test_address, _, _)).Times(0);
std::vector<uint8_t> too_short(0);
GetNotificationEvent(0x0039, too_short);
std::vector<uint8_t> too_long({0x03, 0x01});
@@ -1378,18 +1394,18 @@
TEST_F(VolumeControlCallbackTest, test_audio_input_description_changed) {
std::string descr = "SPDIF";
std::vector<uint8_t> value(descr.begin(), descr.end());
- EXPECT_CALL(*callbacks, OnExtAudioInDescriptionChanged(test_address, 2, descr));
+ EXPECT_CALL(callbacks, OnExtAudioInDescriptionChanged(test_address, _, descr));
GetNotificationEvent(0x005e, value);
}
TEST_F(VolumeControlCallbackTest, test_volume_offset_changed) {
std::vector<uint8_t> value({0x04, 0x05, 0x06});
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, 0x0504));
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, 0x0504));
GetNotificationEvent(0x0082, value);
}
TEST_F(VolumeControlCallbackTest, test_volume_offset_changed_malformed) {
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(0);
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 2, _)).Times(0);
std::vector<uint8_t> too_short({0x04});
GetNotificationEvent(0x0082, too_short);
std::vector<uint8_t> too_long({0x04, 0x05, 0x06, 0x07});
@@ -1398,12 +1414,12 @@
TEST_F(VolumeControlCallbackTest, test_offset_location_changed) {
std::vector<uint8_t> value({0x01, 0x02, 0x03, 0x04});
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201));
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201));
GetNotificationEvent(0x0085, value);
}
TEST_F(VolumeControlCallbackTest, test_offset_location_changed_malformed) {
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(0);
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, _)).Times(0);
std::vector<uint8_t> too_short({0x04});
GetNotificationEvent(0x0085, too_short);
std::vector<uint8_t> too_long({0x04, 0x05, 0x06});
@@ -1413,7 +1429,7 @@
TEST_F(VolumeControlCallbackTest, test_audio_output_description_changed) {
std::string descr = "left";
std::vector<uint8_t> value(descr.begin(), descr.end());
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr));
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr));
GetNotificationEvent(0x008a, value);
}
@@ -1449,7 +1465,7 @@
VolumeControl::Get()->GetExtAudioOutVolumeOffset(test_address, 1);
EXPECT_TRUE(cb);
std::vector<uint8_t> value({0x01, 0x02, 0x03});
- EXPECT_CALL(*callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, 0x0201));
+ EXPECT_CALL(callbacks, OnExtAudioOutVolumeOffsetChanged(test_address, 1, 0x0201));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
@@ -1457,7 +1473,7 @@
VolumeControl::Get()->GetExtAudioOutLocation(test_address, 2);
EXPECT_TRUE(cb);
std::vector<uint8_t> value({0x01, 0x02, 0x03, 0x04});
- EXPECT_CALL(*callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201));
+ EXPECT_CALL(callbacks, OnExtAudioOutLocationChanged(test_address, 2, 0x04030201));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
@@ -1466,32 +1482,32 @@
EXPECT_TRUE(cb);
std::string descr = "right";
std::vector<uint8_t> value(descr.begin(), descr.end());
- EXPECT_CALL(*callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr));
+ EXPECT_CALL(callbacks, OnExtAudioOutDescriptionChanged(test_address, 2, descr));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_state) {
VolumeControl::Get()->GetExtAudioInState(test_address, 1);
EXPECT_TRUE(cb);
- std::vector<uint8_t> value({0x01, 0x00, 0x02, 0x03});
- EXPECT_CALL(*callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, 0x02, false));
+ std::vector<uint8_t> value({0x01, (uint8_t)Mute::NOT_MUTED, 0x02, 0x03});
+ EXPECT_CALL(callbacks, OnExtAudioInStateChanged(test_address, 1, 0x01, Mute::NOT_MUTED, 0x02));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_status) {
- VolumeControl::Get()->GetExtAudioInStatus(test_address, 2);
+ VolumeControl::Get()->GetExtAudioInStatus(test_address, 0);
EXPECT_TRUE(cb);
std::vector<uint8_t> value({static_cast<uint8_t>(bluetooth::vc::VolumeInputStatus::Active)});
- EXPECT_CALL(*callbacks,
- OnExtAudioInStatusChanged(test_address, 2, bluetooth::vc::VolumeInputStatus::Active));
+ EXPECT_CALL(callbacks,
+ OnExtAudioInStatusChanged(test_address, 0, bluetooth::vc::VolumeInputStatus::Active));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
TEST_F(VolumeControlValueGetTest, test_get_ext_audio_in_gain_props) {
- VolumeControl::Get()->GetExtAudioInGainProps(test_address, 2);
+ VolumeControl::Get()->GetExtAudioInGainProps(test_address, 0);
EXPECT_TRUE(cb);
std::vector<uint8_t> value({0x01, 0x02, 0x03});
- EXPECT_CALL(*callbacks, OnExtAudioInGainPropsChanged(test_address, 2, 0x01, 0x02, 0x03));
+ EXPECT_CALL(callbacks, OnExtAudioInGainPropsChanged(test_address, 0, 0x01, 0x02, 0x03));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
@@ -1500,7 +1516,7 @@
EXPECT_TRUE(cb);
std::string descr = "AUX-IN";
std::vector<uint8_t> value(descr.begin(), descr.end());
- EXPECT_CALL(*callbacks, OnExtAudioInDescriptionChanged(test_address, 1, descr));
+ EXPECT_CALL(callbacks, OnExtAudioInDescriptionChanged(test_address, 1, descr));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
@@ -1508,7 +1524,7 @@
VolumeControl::Get()->GetExtAudioInType(test_address, 1);
EXPECT_TRUE(cb);
std::vector<uint8_t> value({static_cast<uint8_t>(bluetooth::vc::VolumeInputType::Ambient)});
- EXPECT_CALL(*callbacks,
+ EXPECT_CALL(callbacks,
OnExtAudioInTypeChanged(test_address, 1, bluetooth::vc::VolumeInputType::Ambient));
cb(conn_id, GATT_SUCCESS, handle, (uint16_t)value.size(), value.data(), cb_data);
}
@@ -1641,11 +1657,11 @@
ASSERT_NE(active_alarm_cb, nullptr);
EXPECT_CALL(*AlarmMock::Get(), AlarmCancel(_)).Times(1);
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address));
GetDisconnectedEvent(test_address, conn_id);
ASSERT_EQ(active_alarm_cb, nullptr);
- Mock::VerifyAndClearExpectations(callbacks.get());
+ Mock::VerifyAndClearExpectations(&callbacks);
}
TEST_F(VolumeControlValueSetTest, test_set_volume) {
@@ -1835,38 +1851,38 @@
std::vector<uint8_t> expected_data(descr.begin(), descr.end());
EXPECT_CALL(gatt_queue,
WriteCharacteristic(conn_id, 0x005e, expected_data, GATT_WRITE_NO_RSP, _, _));
- VolumeControl::Get()->SetExtAudioInDescription(test_address, 2, descr);
+ VolumeControl::Get()->SetExtAudioInDescription(test_address, 1, descr);
}
TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_description_non_writable) {
std::string descr = "AUX";
std::vector<uint8_t> expected_data(descr.begin(), descr.end());
EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
- VolumeControl::Get()->SetExtAudioInDescription(test_address, 1, descr);
+ VolumeControl::Get()->SetExtAudioInDescription(test_address, 0, descr);
}
-TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_value) {
+TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_setting) {
std::vector<uint8_t> expected_data({0x01, 0x00, 0x34});
EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, expected_data, GATT_WRITE, _, _));
- VolumeControl::Get()->SetExtAudioInGainValue(test_address, 2, 0x34);
+ VolumeControl::Get()->SetExtAudioInGainSetting(test_address, 1, 0x34);
}
TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_mode) {
std::vector<uint8_t> mode_manual({0x04, 0x00});
EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, mode_manual, GATT_WRITE, _, _));
- VolumeControl::Get()->SetExtAudioInGainMode(test_address, 2, false);
+ VolumeControl::Get()->SetExtAudioInGainMode(test_address, 1, false);
std::vector<uint8_t> mode_automatic({0x05, 0x00});
EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, mode_automatic, GATT_WRITE, _, _));
- VolumeControl::Get()->SetExtAudioInGainMode(test_address, 2, true);
+ VolumeControl::Get()->SetExtAudioInGainMode(test_address, 1, true);
}
TEST_F(VolumeControlValueSetTest, test_set_ext_audio_in_gain_mute) {
std::vector<uint8_t> mute({0x03, 0x00});
EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, mute, GATT_WRITE, _, _));
- VolumeControl::Get()->SetExtAudioInGainMute(test_address, 2, true);
+ VolumeControl::Get()->SetExtAudioInGainMute(test_address, 1, true);
std::vector<uint8_t> unmute({0x02, 0x00});
EXPECT_CALL(gatt_queue, WriteCharacteristic(conn_id, 0x005c, unmute, GATT_WRITE, _, _));
- VolumeControl::Get()->SetExtAudioInGainMute(test_address, 2, false);
+ VolumeControl::Get()->SetExtAudioInGainMute(test_address, 1, false);
}
class VolumeControlCsis : public VolumeControlTest {
@@ -1932,7 +1948,7 @@
VolumeControl::Get()->SetVolume(group_id, 10);
/* Now inject notification and make sure callback is sent up to Java layer */
- EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true, false));
+ EXPECT_CALL(callbacks, OnGroupVolumeStateChanged(group_id, 0x03, true, false));
std::vector<uint8_t> value({0x03, 0x01, 0x02});
GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value);
@@ -1947,8 +1963,8 @@
VolumeControl::Get()->SetVolume(test_address_1, 20);
VolumeControl::Get()->SetVolume(test_address_2, 20);
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address_1, 20, false, _, false));
- EXPECT_CALL(*callbacks, OnVolumeStateChanged(test_address_2, 20, false, _, false));
+ EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address_1, 20, false, _, false));
+ EXPECT_CALL(callbacks, OnVolumeStateChanged(test_address_2, 20, false, _, false));
std::vector<uint8_t> value2({20, 0x00, 0x03});
GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value2);
GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value2);
@@ -1983,7 +1999,7 @@
GetSearchCompleteEvent(conn_id_2);
/* Now inject notification and make sure callback is sent up to Java layer */
- EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true));
+ EXPECT_CALL(callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true));
std::vector<uint8_t> value({0x03, 0x00, 0x02});
GetNotificationEvent(conn_id_1, test_address_1, 0x0021, value);
@@ -1999,11 +2015,11 @@
GetSearchCompleteEvent(conn_id_2);
/* Disconnect one device. */
- EXPECT_CALL(*callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address_1));
+ EXPECT_CALL(callbacks, OnConnectionState(ConnectionState::DISCONNECTED, test_address_1));
GetDisconnectedEvent(test_address_1, conn_id_1);
/* Now inject notification and make sure callback is sent up to Java layer */
- EXPECT_CALL(*callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true));
+ EXPECT_CALL(callbacks, OnGroupVolumeStateChanged(group_id, 0x03, false, true));
std::vector<uint8_t> value({0x03, 0x00, 0x02});
GetNotificationEvent(conn_id_2, test_address_2, 0x0021, value);
diff --git a/system/btif/Android.bp b/system/btif/Android.bp
index 2402f95..e6bdf90 100644
--- a/system/btif/Android.bp
+++ b/system/btif/Android.bp
@@ -150,6 +150,7 @@
},
},
static_libs: [
+ "aics",
"avrcp-target-service",
"bluetooth_flags_c_lib",
"lib-bt-packets",
@@ -165,6 +166,12 @@
"libbtif-core",
"libflatbuffers-cpp",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
+ shared_libs: [
+ "libbinder",
+ ],
apex_available: [
"com.android.btservices",
],
@@ -243,7 +250,11 @@
"libflatbuffers-cpp",
"libstatslog_bt",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libcrypto",
"libcutils",
],
@@ -279,9 +290,13 @@
"test/btif_storage_test.cc",
],
header_libs: ["libbluetooth_headers"],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"libcrypto",
"libcutils",
"libhidlbase",
@@ -290,6 +305,7 @@
"server_configurable_flags",
],
static_libs: [
+ "aics",
"android.hardware.audio.common@5.0",
"android.hardware.bluetooth.audio@2.0",
"android.hardware.bluetooth.audio@2.1",
@@ -565,9 +581,13 @@
"BluetoothGeneratedDumpsysDataSchema_h",
],
header_libs: ["libbluetooth_headers"],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"libcrypto",
"libcutils",
"libfmq",
@@ -686,9 +706,13 @@
"BluetoothGeneratedDumpsysDataSchema_h",
],
header_libs: ["libbluetooth_headers"],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"libcrypto",
"libcutils",
"libfmq",
diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn
index 884dc60..68ca336 100644
--- a/system/btif/BUILD.gn
+++ b/system/btif/BUILD.gn
@@ -93,6 +93,7 @@
"//bt/system/bta/dm",
"//bt/system/linux_include",
"//bt/system/audio_hearing_aid_hw/include",
+ "//bt/system/bta/aics/include",
"//bt/system/bta/include",
"//bt/system/bta/sys",
"//bt/system/device/include",
@@ -114,6 +115,7 @@
"//bt/system:libbt-platform-protos-lite",
"//bt/system/common",
"//bt/system/profile/avrcp:profile_avrcp",
+ "//bt/system/bta/aics:aics",
]
configs += [
diff --git a/system/btif/avrcp/avrcp_service.cc b/system/btif/avrcp/avrcp_service.cc
index 712f6e0..a1a4574 100644
--- a/system/btif/avrcp/avrcp_service.cc
+++ b/system/btif/avrcp/avrcp_service.cc
@@ -21,8 +21,13 @@
#include <base/threading/thread.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
+#include <stdio.h>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
#include <mutex>
+#include <ostream>
#include <sstream>
#include <string>
#include <utility>
@@ -31,14 +36,26 @@
#include "bta/sys/bta_sys.h"
#include "btif/include/btif_av.h"
#include "btif/include/btif_common.h"
+#include "hardware/avrcp/avrcp.h"
+#include "hardware/avrcp/avrcp_common.h"
+#include "internal_include/bt_target.h"
#include "osi/include/osi.h"
#include "profile/avrcp/avrcp_config.h"
+#include "profile/avrcp/avrcp_internal.h"
+#include "profile/avrcp/avrcp_sdp_records.h"
+#include "profile/avrcp/avrcp_sdp_service.h"
#include "profile/avrcp/device.h"
#include "stack/include/a2dp_api.h"
+#include "stack/include/avct_api.h"
+#include "stack/include/avrc_api.h"
+#include "stack/include/avrc_defs.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/main_thread.h"
#include "stack/include/sdp_api.h"
+#include "stack/include/sdp_callback.h"
+#include "stack/include/sdpdefs.h"
+#include "stack/sdp/sdp_discovery_db.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
diff --git a/system/btif/co/bta_av_co.cc b/system/btif/co/bta_av_co.cc
index de0f906..5cd91c8 100644
--- a/system/btif/co/bta_av_co.cc
+++ b/system/btif/co/bta_av_co.cc
@@ -29,7 +29,11 @@
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
+#include <stdio.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
#include <mutex>
#include <optional>
#include <vector>
@@ -42,16 +46,16 @@
#include "btif/include/btif_a2dp_source.h"
#include "btif/include/btif_av.h"
#include "btif/include/btif_av_co.h"
+#include "device/include/device_iot_conf_defs.h"
#include "device/include/device_iot_config.h"
#include "include/hardware/bt_av.h"
-#include "internal_include/bt_trace.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"
#include "stack/include/a2dp_ext.h"
#include "stack/include/avdt_api.h"
#include "stack/include/bt_hdr.h"
-#include "stack/include/bt_types.h"
#include "stack/include/bt_uuid16.h"
#include "types/raw_address.h"
diff --git a/system/btif/co/bta_av_co_peer.cc b/system/btif/co/bta_av_co_peer.cc
index 5f9356c..4bc9544 100644
--- a/system/btif/co/bta_av_co_peer.cc
+++ b/system/btif/co/bta_av_co_peer.cc
@@ -20,7 +20,18 @@
#include <bluetooth/log.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <mutex>
+#include <vector>
+
#include "bta/include/bta_av_api.h"
+#include "hardware/bt_av.h"
+#include "stack/include/a2dp_codec_api.h"
+#include "stack/include/avdt_api.h"
+#include "stack/include/bt_types.h"
+#include "types/raw_address.h"
using namespace bluetooth;
diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc
index f60a701..12735b6 100644
--- a/system/btif/co/bta_hh_co.cc
+++ b/system/btif/co/bta_hh_co.cc
@@ -18,29 +18,41 @@
#include "bta_hh_co.h"
+#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
#include <fcntl.h>
+#include <linux/hid.h>
+#include <linux/input.h>
#include <linux/uhid.h>
#include <poll.h>
#include <pthread.h>
-#include <stdint.h>
+#include <sched.h>
#include <string.h>
#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
+#include <array>
#include <cerrno>
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
#include "bta_hh_api.h"
#include "btif_config.h"
#include "btif_hh.h"
+#include "hardware/bt_hh.h"
#include "hci/controller_interface.h"
#include "main/shim/entry.h"
+#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/compat.h"
+#include "osi/include/fixed_queue.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "storage/config_keys.h"
#include "types/raw_address.h"
+
#define BTA_HH_NV_LOAD_MAX 16
static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
#define BTA_HH_CACHE_REPORT_VERSION 1
diff --git a/system/btif/co/bta_pan_co.cc b/system/btif/co/bta_pan_co.cc
index db84d8b..0bdcae3 100644
--- a/system/btif/co/bta_pan_co.cc
+++ b/system/btif/co/bta_pan_co.cc
@@ -26,18 +26,15 @@
******************************************************************************/
#include "bta_pan_co.h"
-#include <hardware/bluetooth.h>
-#include <hardware/bt_pan.h>
-#include <string.h>
+#include <bluetooth/log.h>
-#include "bta_api.h"
-#include "bta_pan_api.h"
+#include <cstdint>
+#include <cstring>
+
+#include "bta/include/bta_pan_api.h"
#include "bta_pan_ci.h"
#include "btif_pan_internal.h"
-#include "btif_sock_thread.h"
-#include "btif_util.h"
#include "osi/include/allocator.h"
-#include "pan_api.h"
#include "stack/include/bt_hdr.h"
#include "types/raw_address.h"
diff --git a/system/btif/include/btif_bqr.h b/system/btif/include/btif_bqr.h
index 71105ef..909335b 100644
--- a/system/btif/include/btif_bqr.h
+++ b/system/btif/include/btif_bqr.h
@@ -88,6 +88,8 @@
static constexpr uint32_t kQualityEventMaskConnectFail = 0x1 << 7;
static constexpr uint32_t kQualityEventMaskAdvRFStatsEvent = 0x1 << 8;
static constexpr uint32_t kQualityEventMaskAdvRFStatsMonitor = 0x1 << 9;
+static constexpr uint32_t kQualityEventMaskHealthMonitorStatsEvent = 0x1 << 10;
+static constexpr uint32_t kQualityEventMaskControllerHealthMonitor = 0x1 << 11;
static constexpr uint32_t kQualityEventMaskVendorSpecificQuality = 0x1 << 15;
static constexpr uint32_t kQualityEventMaskLmpMessageTrace = 0x1 << 16;
static constexpr uint32_t kQualityEventMaskBtSchedulingTrace = 0x1 << 17;
@@ -99,6 +101,7 @@
kQualityEventMaskRootInflammation | kQualityEventMaskEnergyMonitoring |
kQualityEventMaskLeAudioChoppy | kQualityEventMaskConnectFail |
kQualityEventMaskAdvRFStatsEvent | kQualityEventMaskAdvRFStatsMonitor |
+ kQualityEventMaskHealthMonitorStatsEvent | kQualityEventMaskControllerHealthMonitor |
kQualityEventMaskVendorSpecificQuality | kQualityEventMaskLmpMessageTrace |
kQualityEventMaskBtSchedulingTrace | kQualityEventMaskControllerDbgInfo |
kQualityEventMaskVendorSpecificTrace;
@@ -132,6 +135,7 @@
static constexpr uint8_t kVersion5_0ParamsTotalLen = 7;
// Added in BQR V6.0
static constexpr uint8_t kVersion6_0ParamsTotalLen = 6;
+
// Warning criteria of the RSSI value.
static constexpr int8_t kCriWarnRssi = -80;
// Warning criteria of the unused AFH channel count.
@@ -176,7 +180,7 @@
static constexpr uint16_t kBqrVersion5_0 = 0x103;
// The REPORT_ACTION_QUERY and BQR_Report_interval starting v1.04(260)
static constexpr uint16_t kBqrVersion6_0 = 0x104;
-
+static constexpr uint16_t kBqrVersion7_0 = 0x105;
// Action definition
//
// Action to Add, Delete or Clear the reporting of quality event(s).
diff --git a/system/btif/include/stack_manager_t.h b/system/btif/include/stack_manager_t.h
index 0e7f00d..f319fff 100644
--- a/system/btif/include/stack_manager_t.h
+++ b/system/btif/include/stack_manager_t.h
@@ -20,6 +20,8 @@
#include <stdbool.h>
+#include <future>
+
#include "core_callbacks.h"
#include "osi/include/future.h"
@@ -32,7 +34,7 @@
ProfileStopCallback);
void (*shut_down_stack_async)(ProfileStopCallback);
void (*clean_up_stack)(ProfileStopCallback);
- void (*start_up_rust_module_async)();
+ void (*start_up_rust_module_async)(std::promise<void> promise);
void (*shut_down_rust_module_async)();
bool (*get_stack_is_running)(void);
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index c4bb371..1e4b693 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -27,32 +27,23 @@
#define LOG_TAG "bt_btif"
-#include <bluetooth/log.h>
-#include <com_android_bluetooth_flags.h>
-#include <hardware/bluetooth.h>
-#include <hardware/bluetooth_headset_interface.h>
-#include <hardware/bt_av.h>
-#include <hardware/bt_csis.h>
-#include <hardware/bt_gatt.h>
-#include <hardware/bt_has.h>
-#include <hardware/bt_hd.h>
-#include <hardware/bt_hearing_aid.h>
-#include <hardware/bt_hf_client.h>
-#include <hardware/bt_hh.h>
-#include <hardware/bt_le_audio.h>
-#include <hardware/bt_pan.h>
-#include <hardware/bt_rc.h>
-#include <hardware/bt_sdp.h>
-#include <hardware/bt_sock.h>
-#include <hardware/bt_vc.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include "hardware/bluetooth.h"
-#include "audio_hal_interface/a2dp_encoding.h"
-#include "bta/hh/bta_hh_int.h" // for HID HACK profile methods
+#include <base/functional/bind.h>
+#include <base/functional/callback.h>
+#include <bluetooth/log.h>
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "bta/hh/bta_hh_int.h"
#include "bta/include/bta_api.h"
#include "bta/include/bta_ar_api.h"
+#include "bta/include/bta_av_api.h"
#include "bta/include/bta_csis_api.h"
#include "bta/include/bta_has_api.h"
#include "bta/include/bta_hearing_aid_api.h"
@@ -66,6 +57,7 @@
#include "btif/include/btif_api.h"
#include "btif/include/btif_av.h"
#include "btif/include/btif_bqr.h"
+#include "btif/include/btif_common.h"
#include "btif/include/btif_config.h"
#include "btif/include/btif_debug_conn.h"
#include "btif/include/btif_dm.h"
@@ -91,11 +83,22 @@
#include "device/include/esco_parameters.h"
#include "device/include/interop.h"
#include "device/include/interop_config.h"
+#include "hardware/avrcp/avrcp.h"
+#include "hardware/bt_csis.h"
+#include "hardware/bt_gatt.h"
+#include "hardware/bt_has.h"
+#include "hardware/bt_hearing_aid.h"
+#include "hardware/bt_le_audio.h"
+#include "hardware/bt_rc.h"
+#include "hardware/bt_sdp.h"
+#include "hardware/bt_sock.h"
+#include "hardware/bt_vc.h"
#include "internal_include/bt_target.h"
#include "main/shim/dumpsys.h"
#include "os/parameter_provider.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
+#include "osi/include/properties.h"
#include "osi/include/stack_power_telemetry.h"
#include "osi/include/wakelock.h"
#include "stack/btm/btm_dev.h"
@@ -104,8 +107,14 @@
#include "stack/include/a2dp_api.h"
#include "stack/include/avct_api.h"
#include "stack/include/avdt_api.h"
+#include "stack/include/avrc_api.h"
+#include "stack/include/bnep_api.h"
+#include "stack/include/bt_name.h"
+#include "stack/include/bt_octets.h"
#include "stack/include/btm_client_interface.h"
#include "stack/include/btm_status.h"
+#include "stack/include/gatt_api.h"
+#include "stack/include/hcidefs.h"
#include "stack/include/hfp_lc3_decoder.h"
#include "stack/include/hfp_lc3_encoder.h"
#include "stack/include/hfp_msbc_decoder.h"
@@ -116,6 +125,7 @@
#include "stack/include/pan_api.h"
#include "stack/include/sdp_api.h"
#include "storage/config_keys.h"
+#include "types/ble_address_with_type.h"
#include "types/bt_transport.h"
#include "types/raw_address.h"
@@ -124,7 +134,6 @@
using bluetooth::csis::CsisClientInterface;
using bluetooth::has::HasClientInterface;
-using bluetooth::hearing_aid::HearingAidInterface;
using bluetooth::le_audio::LeAudioBroadcasterInterface;
using bluetooth::le_audio::LeAudioClientInterface;
using bluetooth::vc::VolumeControlInterface;
@@ -188,7 +197,6 @@
bt_status_t btif_av_sink_execute_service(bool b_enable);
-extern void gatt_tcb_dump(int fd);
extern void bta_gatt_client_dump(int fd);
/*******************************************************************************
@@ -498,7 +506,15 @@
static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(&stop_profiles); }
-static void start_rust_module(void) { stack_manager_get_interface()->start_up_rust_module_async(); }
+static void start_rust_module(void) {
+ std::promise<void> rust_up_promise;
+ auto rust_up_future = rust_up_promise.get_future();
+ stack_manager_get_interface()->start_up_rust_module_async(std::move(rust_up_promise));
+ auto status = rust_up_future.wait_for(std::chrono::milliseconds(1000));
+ if (status != std::future_status::ready) {
+ log::error("Failed to wait for rust initialization in time. May lead to unpredictable crash");
+ }
+}
static void stop_rust_module(void) { stack_manager_get_interface()->shut_down_rust_module_async(); }
diff --git a/system/btif/src/btif_a2dp.cc b/system/btif/src/btif_a2dp.cc
index 01127c3..f7632bf 100644
--- a/system/btif/src/btif_a2dp.cc
+++ b/system/btif/src/btif_a2dp.cc
@@ -23,17 +23,18 @@
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
-#include <stdbool.h>
+
+#include <cstddef>
+#include <cstdint>
#include "audio_hal_interface/a2dp_encoding.h"
+#include "avdt_api.h"
#include "bta_av_api.h"
#include "btif_a2dp_sink.h"
#include "btif_a2dp_source.h"
#include "btif_av.h"
#include "btif_av_co.h"
#include "btif_hf.h"
-#include "btif_util.h"
-#include "internal_include/bt_trace.h"
#include "types/raw_address.h"
using namespace bluetooth;
diff --git a/system/btif/src/btif_a2dp_sink.cc b/system/btif/src/btif_a2dp_sink.cc
index ec9365a..2d214b0 100644
--- a/system/btif/src/btif_a2dp_sink.cc
+++ b/system/btif/src/btif_a2dp_sink.cc
@@ -26,15 +26,23 @@
#include <com_android_bluetooth_flags.h>
#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <future>
#include <mutex>
#include <string>
+#include <utility>
+#include "a2dp_api.h"
+#include "a2dp_codec_api.h"
+#include "avdt_api.h"
+#include "bta_av_api.h"
#include "btif/include/btif_av.h"
#include "btif/include/btif_av_co.h"
#include "btif/include/btif_avrcp_audio_track.h"
#include "btif/include/btif_util.h" // CASE_RETURN_STR
#include "common/message_loop_thread.h"
-#include "hardware/bt_av.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/fixed_queue.h"
diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc
index ae296a4..3f3bc5a 100644
--- a/system/btif/src/btif_a2dp_source.cc
+++ b/system/btif/src/btif_a2dp_source.cc
@@ -20,22 +20,29 @@
#define LOG_TAG "bluetooth-a2dp"
#define ATRACE_TAG ATRACE_TAG_AUDIO
-#include <base/run_loop.h>
+#include "btif_a2dp_source.h"
+
+#include <base/functional/bind.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
-#ifdef __ANDROID__
-#include <cutils/trace.h>
-#endif
-
-#include <limits.h>
-#include <string.h>
+#include <stdio.h>
#include <algorithm>
+#include <chrono>
+#include <cstdint>
+#include <cstring>
#include <future>
+#include <string>
+#include <utility>
+#include <vector>
+#include "a2dp_api.h"
+#include "a2dp_codec_api.h"
#include "audio_hal_interface/a2dp_encoding.h"
+#include "avdt_api.h"
+#include "bt_transport.h"
+#include "bta_av_api.h"
#include "bta_av_ci.h"
-#include "btif_a2dp_source.h"
#include "btif_av.h"
#include "btif_av_co.h"
#include "btif_common.h"
@@ -46,6 +53,7 @@
#include "common/metrics.h"
#include "common/repeating_timer.h"
#include "common/time_util.h"
+#include "hardware/bt_av.h"
#include "osi/include/allocator.h"
#include "osi/include/fixed_queue.h"
#include "osi/include/wakelock.h"
@@ -58,6 +66,10 @@
#include "stack/include/main_thread.h"
#include "types/raw_address.h"
+#ifdef __ANDROID__
+#include <cutils/trace.h>
+#endif
+
using bluetooth::audio::a2dp::BluetoothAudioStatus;
using bluetooth::common::A2dpSessionMetrics;
using bluetooth::common::BluetoothMetricsLogger;
diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index 2132172..8fa008a 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -20,22 +20,33 @@
#include "btif/include/btif_av.h"
-#include <android_bluetooth_sysprop.h>
#include <base/functional/bind.h>
#include <base/strings/stringprintf.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
#include <frameworks/proto_logging/stats/enums/bluetooth/a2dp/enums.pb.h>
#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
+#include <stdio.h>
+#include <chrono>
#include <cstdint>
+#include <cstdio>
+#include <cstring>
#include <future>
+#include <ios>
+#include <map>
#include <mutex>
#include <optional>
+#include <set>
+#include <sstream>
#include <string>
+#include <utility>
#include <vector>
#include "audio_hal_interface/a2dp_encoding.h"
+#include "bta/include/bta_api.h"
+#include "bta/include/bta_api_data_types.h"
+#include "bta/include/bta_av_api.h"
#include "btif/avrcp/avrcp_service.h"
#include "btif/include/btif_a2dp.h"
#include "btif/include/btif_a2dp_sink.h"
@@ -49,17 +60,23 @@
#include "btif/include/stack_manager_t.h"
#include "btif_metrics_logging.h"
#include "common/state_machine.h"
+#include "device/include/device_iot_conf_defs.h"
#include "device/include/device_iot_config.h"
+#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"
+#include "stack/include/a2dp_codec_api.h"
+#include "stack/include/avdt_api.h"
#include "stack/include/avrc_api.h"
+#include "stack/include/avrc_defs.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/btm_ble_api.h"
+#include "stack/include/btm_ble_api_types.h"
#include "stack/include/btm_log_history.h"
#include "stack/include/main_thread.h"
#include "types/raw_address.h"
@@ -3217,7 +3234,7 @@
}
break;
} else {
- FALLTHROUGH_INTENDED;
+ [[fallthrough]];
}
}
case BTA_AV_OFFLOAD_START_RSP_EVT: {
diff --git a/system/btif/src/btif_avrcp_audio_track.cc b/system/btif/src/btif_avrcp_audio_track.cc
index 7a3d27f..fc24963 100644
--- a/system/btif/src/btif_avrcp_audio_track.cc
+++ b/system/btif/src/btif_avrcp_audio_track.cc
@@ -25,17 +25,15 @@
#include <aaudio/AAudio.h>
#include <bluetooth/log.h>
-#include <utils/StrongPointer.h>
#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <thread>
-#include "internal_include/bt_target.h"
-
// TODO(b/369381361) Enfore -Wmissing-prototypes
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-using namespace android;
using namespace bluetooth;
typedef struct {
@@ -80,7 +78,7 @@
trackHolder->stream = stream;
- if (trackHolder != NULL && trackHolder->stream != NULL) {
+ if (trackHolder != nullptr && trackHolder->stream != NULL) {
log::debug("AAudio Error handle: restart A2dp Sink AudioTrack");
AAudioStream_requestStart(trackHolder->stream);
}
diff --git a/system/btif/src/btif_csis_client.cc b/system/btif/src/btif_csis_client.cc
index 2a745ca..65811c6 100644
--- a/system/btif/src/btif_csis_client.cc
+++ b/system/btif/src/btif_csis_client.cc
@@ -18,21 +18,23 @@
#include <base/functional/bind.h>
#include <base/location.h>
#include <bluetooth/log.h>
-#include <hardware/bluetooth.h>
#include <hardware/bt_csis.h>
+#include <atomic>
+#include <memory>
+
#include "bind_helpers.h"
+#include "bluetooth/uuid.h"
#include "bta_csis_api.h"
#include "btif_common.h"
#include "btif_profile_storage.h"
+#include "raw_address.h"
#include "stack/include/main_thread.h"
// TODO(b/369381361) Enfore -Wmissing-prototypes
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
using base::Bind;
-using base::Owned;
-using base::Passed;
using base::Unretained;
using bluetooth::csis::ConnectionState;
using bluetooth::csis::CsisClientCallbacks;
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index 118aa5e..1022425 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -978,7 +978,8 @@
}
}
BTM_LogHistory(kBtmLogTagCallback, bd_addr, "Pin request",
- base::StringPrintf("name:\"%s\" min16:%c", PRIVATE_NAME(bd_name.name),
+ base::StringPrintf("name:\"%s\" min16:%c",
+ PRIVATE_NAME(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);
@@ -3550,7 +3551,8 @@
cod = COD_UNCLASSIFIED;
BTM_LogHistory(kBtmLogTagCallback, bd_addr, "PIN request",
- base::StringPrintf("name:'%s'", PRIVATE_NAME(bd_name.name)));
+ base::StringPrintf("name:'%s'",
+ PRIVATE_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_gatt_client.cc b/system/btif/src/btif_gatt_client.cc
index a873664..075ed1b 100644
--- a/system/btif/src/btif_gatt_client.cc
+++ b/system/btif/src/btif_gatt_client.cc
@@ -332,24 +332,30 @@
// Determine transport
if (transport == BT_TRANSPORT_AUTO) {
- switch (device_type) {
- case BT_DEVICE_TYPE_BREDR:
- transport = BT_TRANSPORT_BR_EDR;
- break;
+ if (com::android::bluetooth::flags::default_gatt_transport()) {
+ // Prefer LE transport when LE is supported
+ transport = (device_type == BT_DEVICE_TYPE_BREDR) ? BT_TRANSPORT_BR_EDR : BT_TRANSPORT_LE;
+ } else {
+ switch (device_type) {
+ case BT_DEVICE_TYPE_BREDR:
+ transport = BT_TRANSPORT_BR_EDR;
+ break;
- case BT_DEVICE_TYPE_BLE:
- transport = BT_TRANSPORT_LE;
- break;
+ case BT_DEVICE_TYPE_BLE:
+ transport = BT_TRANSPORT_LE;
+ break;
- case BT_DEVICE_TYPE_DUMO:
- transport = (addr_type == BLE_ADDR_RANDOM) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR;
- break;
+ case BT_DEVICE_TYPE_DUMO:
+ transport = (addr_type == BLE_ADDR_RANDOM) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR;
+ break;
- default:
- log::error("Unknown device type {}", DeviceTypeText(device_type));
- // transport must not be AUTO for finding control blocks. Use LE for backward compatibility.
- transport = BT_TRANSPORT_LE;
- break;
+ default:
+ log::error("Unknown device type {}", DeviceTypeText(device_type));
+ // transport must not be AUTO for finding control blocks. Use LE for backward
+ // compatibility.
+ transport = BT_TRANSPORT_LE;
+ break;
+ }
}
}
diff --git a/system/btif/src/btif_has_client.cc b/system/btif/src/btif_has_client.cc
index 18ae547..c44485d 100644
--- a/system/btif/src/btif_has_client.cc
+++ b/system/btif/src/btif_has_client.cc
@@ -17,23 +17,25 @@
#include <base/functional/bind.h>
#include <base/location.h>
-#include <hardware/bluetooth.h>
#include <hardware/bt_has.h>
+#include <cstdint>
+#include <memory>
#include <string>
+#include <utility>
+#include <variant>
#include <vector>
#include "bta_has_api.h"
#include "btif_common.h"
#include "btif_profile_storage.h"
+#include "raw_address.h"
#include "stack/include/main_thread.h"
// TODO(b/369381361) Enfore -Wmissing-prototypes
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
using base::Bind;
-using base::Owned;
-using base::Passed;
using base::Unretained;
using bluetooth::has::ConnectionState;
using bluetooth::has::ErrorCode;
diff --git a/system/btif/src/btif_hd.cc b/system/btif/src/btif_hd.cc
index 149b9ae..8b2a673 100644
--- a/system/btif/src/btif_hd.cc
+++ b/system/btif/src/btif_hd.cc
@@ -25,23 +25,29 @@
*
*
***********************************************************************************/
+
#define LOG_TAG "BTIF_HD"
#include "btif/include/btif_hd.h"
#include <bluetooth/log.h>
+#include <string.h>
+#include <cstddef>
#include <cstdint>
+#include <cstring>
#include "bta/include/bta_dm_api.h"
#include "bta/include/bta_hd_api.h"
#include "bta/sys/bta_sys.h"
+#include "bta_api.h"
#include "bta_sec_api.h"
#include "btif/include/btif_common.h"
#include "btif/include/btif_dm.h"
#include "btif/include/btif_hh.h"
#include "btif/include/btif_profile_storage.h"
#include "btif/include/btif_util.h"
+#include "hardware/bluetooth.h"
#include "include/hardware/bt_hd.h"
#include "internal_include/bt_target.h"
#include "osi/include/allocator.h"
diff --git a/system/btif/src/btif_hearing_aid.cc b/system/btif/src/btif_hearing_aid.cc
index 21b134e..64dc35f 100644
--- a/system/btif/src/btif_hearing_aid.cc
+++ b/system/btif/src/btif_hearing_aid.cc
@@ -22,12 +22,16 @@
#include <base/functional/bind.h>
#include <base/location.h>
-#include <hardware/bluetooth.h>
#include <hardware/bt_hearing_aid.h>
+#include <cstdint>
+#include <memory>
+#include <utility>
+
#include "bta_hearing_aid_api.h"
#include "btif_common.h"
#include "btif_profile_storage.h"
+#include "hardware/avrcp/avrcp.h"
#include "stack/include/main_thread.h"
#include "types/raw_address.h"
diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc
index 372bdf4..8edc70a 100644
--- a/system/btif/src/btif_hf.cc
+++ b/system/btif/src/btif_hf.cc
@@ -30,27 +30,40 @@
#include "btif/include/btif_hf.h"
#include <android_bluetooth_sysprop.h>
+#include <base/functional/bind.h>
#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 <cstddef>
#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
#include <string>
+#include <vector>
+#include "bta/ag/bta_ag_int.h"
#include "bta/include/bta_ag_api.h"
+#include "bta/include/bta_api.h"
#include "bta/include/utl.h"
#include "bta_ag_swb_aptx.h"
#include "btif/include/btif_common.h"
#include "btif/include/btif_metrics_logging.h"
#include "btif/include/btif_profile_queue.h"
#include "btif/include/btif_util.h"
+#include "btm_api_types.h"
#include "common/metrics.h"
+#include "device/include/device_iot_conf_defs.h"
#include "device/include/device_iot_config.h"
+#include "hardware/bluetooth.h"
#include "include/hardware/bluetooth_headset_callbacks.h"
#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"
diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc
index 08e06e1..3049545 100644
--- a/system/btif/src/btif_hf_client.cc
+++ b/system/btif/src/btif_hf_client.cc
@@ -49,8 +49,12 @@
#include <bluetooth/log.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_hf_client.h>
-#include <string.h>
+#include <cstdint>
+#include <cstring>
+
+#include "bta/include/bta_api.h"
+#include "bta/include/bta_hfp_api.h"
#include "bta_hf_client_api.h"
#include "btif_common.h"
#include "btif_profile_queue.h"
diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc
index e01e2d8..e1a42df 100644
--- a/system/btif/src/btif_hh.cc
+++ b/system/btif/src/btif_hh.cc
@@ -29,11 +29,23 @@
#include "btif/include/btif_hh.h"
+#include <base/functional/bind.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
+#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>
+#include <unistd.h>
+#include <algorithm>
+#include <cstddef>
#include <cstdint>
+#include <cstring>
+#include "ble_address_with_type.h"
+#include "bluetooth/uuid.h"
+#include "bt_device_type.h"
+#include "bt_transport.h"
+#include "bta_api.h"
+#include "bta_hh_api.h"
#include "bta_hh_co.h"
#include "bta_sec_api.h"
#include "btif/include/btif_common.h"
@@ -43,12 +55,14 @@
#include "btif/include/btif_profile_storage.h"
#include "btif/include/btif_storage.h"
#include "btif/include/btif_util.h"
+#include "hardware/bluetooth.h"
#include "include/hardware/bt_hh.h"
+#include "internal_include/bt_target.h"
#include "main/shim/dumpsys.h"
+#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_uuid16.h"
-#include "stack/include/btm_ble_api.h"
#include "stack/include/btm_client_interface.h"
#include "stack/include/hidh_api.h"
#include "types/raw_address.h"
diff --git a/system/btif/src/btif_iot_config.cc b/system/btif/src/btif_iot_config.cc
index 1e70657..9db2159 100644
--- a/system/btif/src/btif_iot_config.cc
+++ b/system/btif/src/btif_iot_config.cc
@@ -18,9 +18,16 @@
#include <bluetooth/log.h>
+#include <cstdint>
+#include <cstring>
+
+#include "bt_name.h"
#include "bta_sec_api.h"
#include "btif_storage.h"
+#include "device/include/device_iot_conf_defs.h"
#include "device/include/device_iot_config.h"
+#include "hardware/bluetooth.h"
+#include "raw_address.h"
#include "stack/include/btm_ble_api.h"
#include "stack/include/btm_client_interface.h"
diff --git a/system/btif/src/btif_le_audio.cc b/system/btif/src/btif_le_audio.cc
index 0e4ab09..8498dab 100644
--- a/system/btif/src/btif_le_audio.cc
+++ b/system/btif/src/btif_le_audio.cc
@@ -16,14 +16,17 @@
*/
#include <bluetooth/log.h>
-#include <hardware/bluetooth.h>
#include <hardware/bt_le_audio.h>
+#include <atomic>
+#include <cstdint>
+#include <memory>
#include <vector>
#include "bta_le_audio_api.h"
#include "btif_common.h"
#include "btif_profile_storage.h"
+#include "raw_address.h"
#include "stack/include/main_thread.h"
// TODO(b/369381361) Enfore -Wmissing-prototypes
diff --git a/system/btif/src/btif_le_audio_broadcaster.cc b/system/btif/src/btif_le_audio_broadcaster.cc
index 45c4b5b..253c0e0 100644
--- a/system/btif/src/btif_le_audio_broadcaster.cc
+++ b/system/btif/src/btif_le_audio_broadcaster.cc
@@ -16,9 +16,15 @@
*/
#include <base/functional/bind.h>
-#include <hardware/bluetooth.h>
#include <hardware/bt_le_audio.h>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
#include "bta_le_audio_api.h"
#include "bta_le_audio_broadcaster_api.h"
#include "btif_common.h"
diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc
index 53c7cdb..1f0bcb1 100644
--- a/system/btif/src/btif_pan.cc
+++ b/system/btif/src/btif_pan.cc
@@ -29,7 +29,6 @@
#include "btif/include/btif_pan.h"
-#include <android_bluetooth_sysprop.h>
#include <arpa/inet.h>
#include <base/functional/bind.h>
#include <base/location.h>
@@ -39,13 +38,24 @@
#include <linux/if_tun.h>
#include <net/if.h>
#include <poll.h>
+#include <string.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
#include <unistd.h>
+#include <cerrno>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
#include "bta/include/bta_pan_api.h"
#include "btif/include/btif_common.h"
#include "btif/include/btif_pan_internal.h"
#include "btif/include/btif_sock_thread.h"
+#include "hardware/bluetooth.h"
#include "hci/controller_interface.h"
#include "include/hardware/bt_pan.h"
#include "internal_include/bt_target.h"
@@ -53,6 +63,7 @@
#include "main/shim/helpers.h"
#include "osi/include/allocator.h"
#include "osi/include/compat.h"
+#include "osi/include/osi.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/main_thread.h"
#include "stack/include/pan_api.h"
diff --git a/system/btif/src/btif_profile_queue.cc b/system/btif/src/btif_profile_queue.cc
index 15237ab..38d00f4 100644
--- a/system/btif/src/btif_profile_queue.cc
+++ b/system/btif/src/btif_profile_queue.cc
@@ -33,10 +33,13 @@
#include <bluetooth/log.h>
#include <string.h>
+#include <cstdint>
#include <list>
+#include <string>
#include "btif/include/stack_manager_t.h"
#include "btif_common.h"
+#include "hardware/bluetooth.h"
#include "types/raw_address.h"
using namespace bluetooth;
diff --git a/system/btif/src/btif_profile_storage.cc b/system/btif/src/btif_profile_storage.cc
index d0949d6..2301019 100644
--- a/system/btif/src/btif_profile_storage.cc
+++ b/system/btif/src/btif_profile_storage.cc
@@ -15,6 +15,7 @@
* limitations under the License.
*
******************************************************************************/
+
#define LOG_TAG "bt_btif_profile_storage"
#include "btif_profile_storage.h"
@@ -26,8 +27,13 @@
#include <string.h>
#include <time.h>
+#include <cstdint>
+#include <string>
+#include <utility>
#include <vector>
+#include "ble_address_with_type.h"
+#include "bt_transport.h"
#include "bta_csis_api.h"
#include "bta_groups.h"
#include "bta_has_api.h"
@@ -41,6 +47,7 @@
#include "btif_config.h"
#include "btif_hh.h"
#include "btif_storage.h"
+#include "hardware/bluetooth.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/main_thread.h"
#include "storage/config_keys.h"
diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc
index cf24440..5b97f45 100644
--- a/system/btif/src/btif_rc.cc
+++ b/system/btif/src/btif_rc.cc
@@ -26,17 +26,19 @@
#include "btif_rc.h"
+#include <base/functional/bind.h>
#include <bluetooth/log.h>
-#include <fcntl.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_rc.h>
-#include <pthread.h>
+#include <stdio.h>
#include <string.h>
#include <time.h>
-#include <unistd.h>
+#include <cstdint>
#include <cstdio>
#include <mutex>
+#include <sstream>
+#include <string>
#include "bta/include/bta_av_api.h"
#include "btif/avrcp/avrcp_service.h"
@@ -48,6 +50,7 @@
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
#include "osi/include/list.h"
+#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "stack/include/avrc_api.h"
#include "stack/include/avrc_defs.h"
@@ -1246,7 +1249,7 @@
bool btif_rc_is_connected_peer(const RawAddress& peer_addr) {
for (int idx = 0; idx < BTIF_RC_NUM_CONN; idx++) {
btif_rc_device_cb_t* p_dev = get_connected_device(idx);
- if (p_dev != NULL && (p_dev->rc_connected == TRUE) && peer_addr == p_dev->rc_addr) {
+ if (p_dev != NULL && p_dev->rc_connected && peer_addr == p_dev->rc_addr) {
return true;
}
}
@@ -1666,7 +1669,7 @@
case AVRC_PDU_REQUEST_CONTINUATION_RSP: {
log::verbose("REQUEST CONTINUATION: target_pdu: 0x{:02d}", pavrc_cmd->continu.target_pdu);
tAVRC_RESPONSE avrc_rsp;
- if (p_dev->rc_connected == TRUE) {
+ if (p_dev->rc_connected) {
memset(&(avrc_rsp.continu), 0, sizeof(tAVRC_NEXT_RSP));
avrc_rsp.continu.opcode = opcode_from_pdu(AVRC_PDU_REQUEST_CONTINUATION_RSP);
avrc_rsp.continu.pdu = AVRC_PDU_REQUEST_CONTINUATION_RSP;
@@ -1679,7 +1682,7 @@
case AVRC_PDU_ABORT_CONTINUATION_RSP: {
log::verbose("ABORT CONTINUATION: target_pdu: 0x{:02d}", pavrc_cmd->abort.target_pdu);
tAVRC_RESPONSE avrc_rsp;
- if (p_dev->rc_connected == TRUE) {
+ if (p_dev->rc_connected) {
memset(&(avrc_rsp.abort), 0, sizeof(tAVRC_NEXT_RSP));
avrc_rsp.abort.opcode = opcode_from_pdu(AVRC_PDU_ABORT_CONTINUATION_RSP);
avrc_rsp.abort.pdu = AVRC_PDU_ABORT_CONTINUATION_RSP;
diff --git a/system/btif/src/btif_vc.cc b/system/btif/src/btif_vc.cc
index e106aed..22b5091 100644
--- a/system/btif/src/btif_vc.cc
+++ b/system/btif/src/btif_vc.cc
@@ -17,12 +17,19 @@
/* Volume Control Interface */
+#include <aics/api.h>
#include <base/functional/bind.h>
#include <base/location.h>
#include <bluetooth/log.h>
-#include <hardware/bluetooth.h>
#include <hardware/bt_vc.h>
+#include <atomic>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <variant>
+
#include "bta/include/bta_vc_api.h"
#include "btif/include/btif_common.h"
#include "btif/include/btif_profile_storage.h"
@@ -34,6 +41,7 @@
using base::Bind;
using base::Unretained;
+using bluetooth::aics::Mute;
using bluetooth::vc::ConnectionState;
using bluetooth::vc::VolumeControlCallbacks;
using bluetooth::vc::VolumeControlInterface;
@@ -102,10 +110,10 @@
}
/* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */
- void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val,
- uint8_t gain_mode, bool mute) override {
+ void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id,
+ int8_t gain_setting, ::Mute mute, uint8_t gain_mode) override {
do_in_jni_thread(Bind(&VolumeControlCallbacks::OnExtAudioInStateChanged, Unretained(callbacks_),
- address, ext_input_id, gain_val, gain_mode, mute));
+ address, ext_input_id, gain_setting, mute, gain_mode));
}
void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id,
@@ -351,8 +359,8 @@
Unretained(VolumeControl::Get()), address, ext_input_id, descr));
}
- void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id,
- int8_t value) override {
+ void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id,
+ int8_t gain_setting) override {
if (!initialized || !VolumeControl::IsVolumeControlRunning()) {
bluetooth::log::verbose(
"call ignored, due to already started cleanup procedure or service "
@@ -360,8 +368,8 @@
return;
}
- do_in_main_thread(Bind(&VolumeControl::SetExtAudioInGainValue, Unretained(VolumeControl::Get()),
- address, ext_input_id, value));
+ do_in_main_thread(Bind(&VolumeControl::SetExtAudioInGainSetting,
+ Unretained(VolumeControl::Get()), address, ext_input_id, gain_setting));
}
void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id,
diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc
index 93407fc..ace7f8e 100644
--- a/system/btif/src/stack_manager.cc
+++ b/system/btif/src/stack_manager.cc
@@ -125,7 +125,7 @@
ProfileStopCallback stopProfiles);
static void event_shut_down_stack(ProfileStopCallback stopProfiles);
static void event_clean_up_stack(std::promise<void> promise, ProfileStopCallback stopProfiles);
-static void event_start_up_rust_module();
+static void event_start_up_rust_module(std::promise<void> promise);
static void event_shut_down_rust_module();
static void event_signal_stack_up(void* context);
@@ -183,8 +183,9 @@
}
}
-static void start_up_rust_module_async() {
- management_thread.DoInThread(FROM_HERE, base::BindOnce(event_start_up_rust_module));
+static void start_up_rust_module_async(std::promise<void> promise) {
+ management_thread.DoInThread(FROM_HERE,
+ base::BindOnce(event_start_up_rust_module, std::move(promise)));
}
static void shut_down_rust_module_async() {
@@ -391,9 +392,10 @@
info("finished");
}
-static void event_start_up_rust_module() {
+static void event_start_up_rust_module(std::promise<void> promise) {
info("is bringing up the Rust module");
module_start_up(get_local_module(RUST_MODULE));
+ promise.set_value();
info("finished");
}
diff --git a/system/gd/Android.bp b/system/gd/Android.bp
index c74cff9..ff26e0b 100644
--- a/system/gd/Android.bp
+++ b/system/gd/Android.bp
@@ -58,13 +58,13 @@
soong_config_variables: {
vertical: {
android_desktop: {
- srcs: [":BluetoothHalSources_mgmt"],
+ srcs: [":BluetoothOsSources_mgmt_linux"],
},
android_default: {
- srcs: [":BluetoothHalSources_mgmt_stub"],
+ srcs: [":BluetoothOsSources_mgmt"],
},
conditions_default: {
- srcs: [":BluetoothHalSources_mgmt_stub"],
+ srcs: [":BluetoothOsSources_mgmt"],
},
},
},
diff --git a/system/gd/hal/Android.bp b/system/gd/hal/Android.bp
index 1086c31..91e1573 100644
--- a/system/gd/hal/Android.bp
+++ b/system/gd/hal/Android.bp
@@ -52,20 +52,6 @@
}
filegroup {
- name: "BluetoothHalSources_mgmt_stub",
- srcs: [
- "mgmt_stub.cc",
- ],
-}
-
-filegroup {
- name: "BluetoothHalSources_mgmt",
- srcs: [
- "mgmt.cc",
- ],
-}
-
-filegroup {
name: "BluetoothHalSources_ranging_android",
srcs: [
"ranging_hal_android.cc",
diff --git a/system/gd/hal/BUILD.gn b/system/gd/hal/BUILD.gn
index f0a2f9d..46be6e9 100644
--- a/system/gd/hal/BUILD.gn
+++ b/system/gd/hal/BUILD.gn
@@ -34,12 +34,10 @@
if (use.floss_rootcanal) {
sources = [
"hci_hal_host_rootcanal.cc",
- "mgmt.cc",
]
} else {
sources = [
"hci_hal_host.cc",
- "mgmt.cc",
]
}
diff --git a/system/gd/hal/hci_hal_android.cc b/system/gd/hal/hci_hal_android.cc
index 3e66f98..51bc789 100644
--- a/system/gd/hal/hci_hal_android.cc
+++ b/system/gd/hal/hci_hal_android.cc
@@ -24,8 +24,8 @@
#include "hal/hci_backend.h"
#include "hal/hci_hal.h"
#include "hal/link_clocker.h"
-#include "hal/mgmt.h"
#include "hal/snoop_logger.h"
+#include "os/mgmt.h"
namespace bluetooth::hal {
@@ -158,7 +158,9 @@
backend_->sendIsoData(packet);
}
- uint16_t getMsftOpcode() override { return Mgmt().get_vs_opcode(MGMT_VS_OPCODE_MSFT); }
+ uint16_t getMsftOpcode() override {
+ return os::Management::getInstance().getVendorSpecificCode(MGMT_VS_OPCODE_MSFT);
+ }
protected:
void ListDependencies(ModuleList* list) const override {
diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc
index 79e1cab..e00554c 100644
--- a/system/gd/hal/hci_hal_host.cc
+++ b/system/gd/hal/hci_hal_host.cc
@@ -34,9 +34,9 @@
#include "hal/hci_hal.h"
#include "hal/link_clocker.h"
-#include "hal/mgmt.h"
#include "hal/snoop_logger.h"
#include "metrics/counter_metrics.h"
+#include "os/mgmt.h"
#include "os/reactor.h"
#include "os/thread.h"
@@ -312,7 +312,9 @@
write_to_fd(packet);
}
- uint16_t getMsftOpcode() override { return Mgmt().get_vs_opcode(MGMT_VS_OPCODE_MSFT); }
+ uint16_t getMsftOpcode() override {
+ return os::Management::getInstance().getVendorSpecificCode(MGMT_VS_OPCODE_MSFT);
+ }
void markControllerBroken() override {
std::lock_guard<std::mutex> lock(api_mutex_);
diff --git a/system/gd/hal/ranging_hal.h b/system/gd/hal/ranging_hal.h
index 981f16b..40afe0b 100644
--- a/system/gd/hal/ranging_hal.h
+++ b/system/gd/hal/ranging_hal.h
@@ -23,6 +23,12 @@
namespace bluetooth {
namespace hal {
+enum RangingHalVersion {
+ V_UNKNOWN = 0,
+ V_1 = 1,
+ V_2 = 2,
+};
+
struct VendorSpecificCharacteristic {
std::array<uint8_t, 16> characteristicUuid_;
std::vector<uint8_t> value_;
diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc
index c50ee18..c24a40c 100644
--- a/system/gd/hal/ranging_hal_android.cc
+++ b/system/gd/hal/ranging_hal_android.cc
@@ -109,6 +109,8 @@
public:
bool IsBound() override { return bluetooth_channel_sounding_ != nullptr; }
+ RangingHalVersion GetRangingHalVersion() { return hal_ver_; }
+
void RegisterCallback(RangingHalCallback* callback) { ranging_hal_callback_ = callback; }
std::vector<VendorSpecificCharacteristic> GetVendorSpecificCharacteristics() override {
@@ -248,6 +250,17 @@
protected:
void ListDependencies(ModuleList* /*list*/) const {}
+ RangingHalVersion get_ranging_hal_version() {
+ int ver = 0;
+ auto aidl_ret = bluetooth_channel_sounding_->getInterfaceVersion(&ver);
+ if (aidl_ret.isOk()) {
+ log::info("ranging HAL version - {}", ver);
+ return static_cast<RangingHalVersion>(ver);
+ }
+ log::warn("ranging HAL version is not available.");
+ return RangingHalVersion::V_UNKNOWN;
+ }
+
void Start() override {
std::string instance = std::string() + IBluetoothChannelSounding::descriptor + "/default";
log::info("AServiceManager_isDeclared {}", AServiceManager_isDeclared(instance.c_str()));
@@ -255,6 +268,9 @@
::ndk::SpAIBinder binder(AServiceManager_waitForService(instance.c_str()));
bluetooth_channel_sounding_ = IBluetoothChannelSounding::fromBinder(binder);
log::info("Bind IBluetoothChannelSounding {}", IsBound() ? "Success" : "Fail");
+ if (bluetooth_channel_sounding_ != nullptr) {
+ hal_ver_ = get_ranging_hal_version();
+ }
}
}
@@ -267,6 +283,7 @@
RangingHalCallback* ranging_hal_callback_;
std::unordered_map<uint16_t, std::shared_ptr<BluetoothChannelSoundingSessionTracker>>
session_trackers_;
+ RangingHalVersion hal_ver_;
};
const ModuleFactory RangingHal::Factory = ModuleFactory([]() { return new RangingHalAndroid(); });
diff --git a/system/gd/hal/ranging_hal_host.cc b/system/gd/hal/ranging_hal_host.cc
index 36c821f..b11d20d 100644
--- a/system/gd/hal/ranging_hal_host.cc
+++ b/system/gd/hal/ranging_hal_host.cc
@@ -27,6 +27,7 @@
class RangingHalHost : public RangingHal {
public:
bool IsBound() override { return false; }
+ RangingHalVersion GetRangingHalVersion() { return V_UNKNOWN; }
void RegisterCallback(RangingHalCallback* /* callback */) override {}
std::vector<VendorSpecificCharacteristic> GetVendorSpecificCharacteristics() override {
std::vector<VendorSpecificCharacteristic> vendor_specific_characteristics = {};
diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc
index 6b9fc8a..0fc1939 100644
--- a/system/gd/hal/snoop_logger.cc
+++ b/system/gd/hal/snoop_logger.cc
@@ -23,7 +23,7 @@
#include <com_android_bluetooth_flags.h>
#ifdef __ANDROID__
#include <cutils/trace.h>
-#endif // __ANDROID__
+#endif // __ANDROID__
#include <sys/stat.h>
#include <algorithm>
@@ -469,8 +469,6 @@
// PBAP, MAP and HFP packets filter mode - disabled
const std::string SnoopLogger::kBtSnoopLogFilterProfileModeDisabled = "disabled";
-std::string SnoopLogger::btsnoop_mode_;
-
// Consts accessible in unit tests
const size_t SnoopLogger::PACKET_TYPE_LENGTH = 1;
const size_t SnoopLogger::MAX_HCI_ACL_LEN = 14;
@@ -482,7 +480,8 @@
const std::chrono::milliseconds snooz_log_life_time,
const std::chrono::milliseconds snooz_log_delete_alarm_interval,
bool snoop_log_persists)
- : snoop_log_path_(std::move(snoop_log_path)),
+ : btsnoop_mode_(btsnoop_mode),
+ snoop_log_path_(std::move(snoop_log_path)),
snooz_log_path_(std::move(snooz_log_path)),
max_packets_per_file_(max_packets_per_file),
btsnooz_buffer_(max_packets_per_buffer),
@@ -490,8 +489,6 @@
snooz_log_life_time_(snooz_log_life_time),
snooz_log_delete_alarm_interval_(snooz_log_delete_alarm_interval),
snoop_log_persists(snoop_log_persists) {
- btsnoop_mode_ = btsnoop_mode;
-
if (btsnoop_mode_ == kBtSnoopLogModeFiltered) {
log::info("Snoop Logs filtered mode enabled");
EnableFilters();
@@ -566,9 +563,6 @@
}
void SnoopLogger::EnableFilters() {
- if (btsnoop_mode_ != kBtSnoopLogModeFiltered) {
- return;
- }
std::lock_guard<std::mutex> lock(snoop_log_filters_mutex);
for (auto itr = kBtSnoopLogFilterState.begin(); itr != kBtSnoopLogFilterState.end(); itr++) {
auto filter_enabled_property = os::GetSystemProperty(itr->first);
@@ -1135,7 +1129,7 @@
if (com::android::bluetooth::flags::snoop_logger_tracing()) {
LogTracePoint(packet, direction, type);
}
- #endif // __ANDROID__
+#endif // __ANDROID__
uint64_t timestamp_us = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch())
@@ -1305,7 +1299,7 @@
socket_ = nullptr;
}
- btsnoop_mode_.clear();
+ btsnoop_mode_ = kBtSnoopLogModeDisabled;
// Disable all filters
DisableFilters();
@@ -1350,36 +1344,26 @@
return btsnooz_max_memory_usage_bytes / kDefaultBtSnoozMaxBytesPerPacket;
}
-std::string SnoopLogger::GetBtSnoopMode() {
+std::string SnoopLogger::GetCurrentSnoopMode() { return btsnoop_mode_; }
+
+static std::string GetBtSnoopMode() {
// Default mode is FILTERED on userdebug/eng build, DISABLED on user build.
// In userdebug/eng build, it can also be overwritten by modifying the global setting
- std::string default_mode = kBtSnoopLogModeDisabled;
- {
- auto is_debuggable = os::GetSystemPropertyBool(kIsDebuggableProperty, false);
- if (is_debuggable) {
- auto default_mode_property = os::GetSystemProperty(kBtSnoopDefaultLogModeProperty);
- if (default_mode_property) {
- default_mode = std::move(default_mode_property.value());
- } else {
- default_mode = kBtSnoopLogModeFiltered;
- }
- }
+ std::string btsnoop_mode = SnoopLogger::kBtSnoopLogModeDisabled;
+ if (os::GetSystemPropertyBool(SnoopLogger::kIsDebuggableProperty, false)) {
+ btsnoop_mode = os::GetSystemProperty(SnoopLogger::kBtSnoopDefaultLogModeProperty)
+ .value_or(SnoopLogger::kBtSnoopLogModeFiltered);
}
- // Get the actual mode if exist
- std::string btsnoop_mode = default_mode;
- {
- auto btsnoop_mode_prop = os::GetSystemProperty(kBtSnoopLogModeProperty);
- if (btsnoop_mode_prop) {
- btsnoop_mode = std::move(btsnoop_mode_prop.value());
- }
- }
+ btsnoop_mode = os::GetSystemProperty(SnoopLogger::kBtSnoopLogModeProperty).value_or(btsnoop_mode);
- // If Snoop Logger already set up, return current mode
- bool btsnoop_mode_empty = btsnoop_mode_.empty();
- log::info("btsnoop_mode_empty: {}", btsnoop_mode_empty);
- if (!btsnoop_mode_empty) {
- return btsnoop_mode_;
+ // Only allow a subset of values:
+ if (!(btsnoop_mode == SnoopLogger::kBtSnoopLogModeDisabled ||
+ btsnoop_mode == SnoopLogger::kBtSnoopLogModeFull ||
+ btsnoop_mode == SnoopLogger::kBtSnoopLogModeFiltered ||
+ btsnoop_mode == SnoopLogger::kBtSnoopLogModeKernel)) {
+ log::warn("{}: Invalid btsnoop value, default back to disabled", btsnoop_mode);
+ return SnoopLogger::kBtSnoopLogModeDisabled;
}
return btsnoop_mode;
@@ -1463,7 +1447,7 @@
} break;
}
}
-#endif // __ANDROID__
+#endif // __ANDROID__
} // namespace hal
} // namespace bluetooth
diff --git a/system/gd/hal/snoop_logger.h b/system/gd/hal/snoop_logger.h
index 3566630..bcd406c 100644
--- a/system/gd/hal/snoop_logger.h
+++ b/system/gd/hal/snoop_logger.h
@@ -199,9 +199,8 @@
static size_t GetMaxPacketsPerBuffer();
- // Get snoop logger mode based on current system setup
- // Changes to this values is only effective after restarting Bluetooth
- static std::string GetBtSnoopMode();
+ // Get current snoop logger mode
+ std::string GetCurrentSnoopMode();
// Returns whether the soc manufacturer is Qualcomm
// Changes to this value is only effective after restarting Bluetooth
@@ -232,7 +231,7 @@
// Set a RFCOMM dlci as acceptlisted, allowing packets with that RFCOMM CID
// to show up in the snoop logs. The local_cid is used to associate it with
- // its corrisponding ACL connection. The dlci is the channel with direction
+ // its corresponding ACL connection. The dlci is the channel with direction
// so there is no chance of a collision if two services are using the same
// channel but in different directions.
void AcceptlistRfcommDlci(uint16_t conn_handle, uint16_t local_cid, uint8_t dlci);
@@ -305,7 +304,7 @@
uint32_t FilterProfiles(bool is_received, uint8_t* packet);
// Check if packet is A2DP media packet (a2dppktsfiltered mode)
bool IsA2dpMediaPacket(bool is_received, uint8_t* packet);
- // Chec if channel is cached in snoop logger for filtering (a2dppktsfiltered mode)
+ // Check if channel is cached in snoop logger for filtering (a2dppktsfiltered mode)
bool IsA2dpMediaChannel(uint16_t conn_handle, uint16_t cid, bool is_local_cid);
// Handle HFP filtering while profilesfiltered enabled
uint32_t FilterProfilesHandleHfp(uint8_t* packet, uint32_t length, uint32_t totlen,
@@ -319,12 +318,12 @@
std::unique_ptr<SnoopLoggerSocketThread> snoop_logger_socket_thread_;
- #ifdef __ANDROID__
+#ifdef __ANDROID__
void LogTracePoint(const HciPacket& packet, Direction direction, PacketType type);
- #endif // __ANDROID__
+#endif // __ANDROID__
private:
- static std::string btsnoop_mode_;
+ std::string btsnoop_mode_;
std::string snoop_log_path_;
std::string snooz_log_path_;
std::ofstream btsnoop_ostream_;
diff --git a/system/gd/hci/acl_manager/classic_impl.h b/system/gd/hci/acl_manager/classic_impl.h
index ca0baf7..08cdcbd 100644
--- a/system/gd/hci/acl_manager/classic_impl.h
+++ b/system/gd/hci/acl_manager/classic_impl.h
@@ -624,6 +624,11 @@
auto view = ReadRemoteSupportedFeaturesCompleteView::Create(packet);
log::assert_that(view.IsValid(), "Read remote supported features packet invalid");
uint16_t handle = view.GetConnectionHandle();
+ auto status = view.GetStatus();
+ if (status != ErrorCode::SUCCESS) {
+ log::error("handle:{} status:{}", handle, ErrorCodeText(status));
+ return;
+ }
bluetooth::os::LogMetricBluetoothRemoteSupportedFeatures(connections.get_address(handle), 0,
view.GetLmpFeatures(), handle);
connections.execute(handle, [=](ConnectionManagementCallbacks* callbacks) {
@@ -635,6 +640,11 @@
auto view = ReadRemoteExtendedFeaturesCompleteView::Create(packet);
log::assert_that(view.IsValid(), "Read remote extended features packet invalid");
uint16_t handle = view.GetConnectionHandle();
+ auto status = view.GetStatus();
+ if (status != ErrorCode::SUCCESS) {
+ log::error("handle:{} status:{}", handle, ErrorCodeText(status));
+ return;
+ }
bluetooth::os::LogMetricBluetoothRemoteSupportedFeatures(connections.get_address(handle),
view.GetPageNumber(),
view.GetExtendedLmpFeatures(), handle);
diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc
index 5dcd379..08fe9fb 100644
--- a/system/gd/hci/distance_measurement_manager.cc
+++ b/system/gd/hci/distance_measurement_manager.cc
@@ -47,7 +47,8 @@
static constexpr uint8_t kTxPowerNotAvailable = 0xfe;
static constexpr int8_t kRSSIDropOffAt1M = 41;
static constexpr uint8_t kCsMaxTxPower = 10; // 10 dBm
-static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection = CsSyncAntennaSelection::ANTENNA_2;
+static constexpr CsSyncAntennaSelection kCsSyncAntennaSelection =
+ CsSyncAntennaSelection::ANTENNAS_IN_ORDER;
static constexpr uint8_t kConfigId = 0x01; // Use 0x01 to create config and enable procedure
static constexpr uint8_t kMinMainModeSteps = 0x02;
static constexpr uint8_t kMaxMainModeSteps = 0x05;
@@ -129,8 +130,9 @@
bool contains_sounding_sequence_remote_;
CsProcedureDoneStatus local_status;
CsProcedureDoneStatus remote_status;
- // If the procedure is aborted by either the local or remote side.
- bool aborted = false;
+ // If any subevent is received with a Subevent_Done_Status of 0x0 (All results complete for the
+ // CS subevent)
+ bool contains_complete_subevent_ = false;
// RAS data
SegmentationHeader segmentation_header_;
RangingHeader ranging_header_;
@@ -1121,12 +1123,14 @@
return;
}
procedure_data->ras_subevent_header_.num_steps_reported_ += result_data_structures.size();
+ if (subevent_done_status == CsSubeventDoneStatus::ALL_RESULTS_COMPLETE) {
+ procedure_data->contains_complete_subevent_ = true;
+ }
if (procedure_abort_reason != ProcedureAbortReason::NO_ABORT ||
subevent_abort_reason != SubeventAbortReason::NO_ABORT) {
// Even the procedure is aborted, we should keep following process and
// handle it when all corresponding remote data received.
- procedure_data->aborted = true;
procedure_data->ras_subevent_header_.ranging_abort_reason_ =
static_cast<RangingAbortReason>(procedure_abort_reason);
procedure_data->ras_subevent_header_.subevent_abort_reason_ =
@@ -1663,7 +1667,7 @@
if (live_tracker->local_start &&
procedure_data->local_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE &&
procedure_data->remote_status == CsProcedureDoneStatus::ALL_RESULTS_COMPLETE &&
- !procedure_data->aborted) {
+ procedure_data->contains_complete_subevent_) {
log::debug("Procedure complete counter:{} data size:{}, main_mode_type:{}, sub_mode_type:{}",
(uint16_t)procedure_data->counter, (uint16_t)procedure_data->step_channel.size(),
(uint16_t)live_tracker->main_mode_type, (uint16_t)live_tracker->sub_mode_type);
@@ -1684,7 +1688,6 @@
raw_data.packet_quality_initiator = procedure_data->packet_quality_initiator;
raw_data.packet_quality_reflector = procedure_data->packet_quality_reflector;
ranging_hal_->WriteRawData(connection_handle, raw_data);
- return;
}
}
diff --git a/system/gd/metrics/chromeos/metrics_event.cc b/system/gd/metrics/chromeos/metrics_event.cc
index a8c8c46..806db26 100644
--- a/system/gd/metrics/chromeos/metrics_event.cc
+++ b/system/gd/metrics/chromeos/metrics_event.cc
@@ -15,6 +15,7 @@
*/
#include "metrics/chromeos/metrics_event.h"
+#include <android-base/parseint.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/strings/pattern.h>
@@ -665,7 +666,7 @@
int64_t id;
if (base::ReadFileToString(base::FilePath(path).Append(file), &content)) {
- if (base::HexStringToInt64(base::CollapseWhitespaceASCII(content, false), &id)) {
+ if (android::base::ParseInt(base::CollapseWhitespaceASCII(content, false), &id)) {
return id;
}
}
diff --git a/system/gd/os/Android.bp b/system/gd/os/Android.bp
index a716973..1f4f4b4 100644
--- a/system/gd/os/Android.bp
+++ b/system/gd/os/Android.bp
@@ -126,3 +126,17 @@
"system_properties_common.cc",
],
}
+
+filegroup {
+ name: "BluetoothOsSources_mgmt",
+ srcs: [
+ "mgmt_stub.cc",
+ ],
+}
+
+filegroup {
+ name: "BluetoothOsSources_mgmt_linux",
+ srcs: [
+ "linux_generic/mgmt.cc",
+ ],
+}
diff --git a/system/gd/os/BUILD.gn b/system/gd/os/BUILD.gn
index 6824184..7bd3c7c 100644
--- a/system/gd/os/BUILD.gn
+++ b/system/gd/os/BUILD.gn
@@ -53,6 +53,7 @@
"handler.cc",
"linux_generic/alarm.cc",
"linux_generic/files.cc",
+ "linux_generic/mgmt.cc",
"linux_generic/reactive_semaphore.cc",
"linux_generic/reactor.cc",
"linux_generic/repeating_alarm.cc",
diff --git a/system/gd/hal/mgmt.cc b/system/gd/os/linux_generic/mgmt.cc
similarity index 95%
rename from system/gd/hal/mgmt.cc
rename to system/gd/os/linux_generic/mgmt.cc
index c5de32c..8f2fbd0 100644
--- a/system/gd/hal/mgmt.cc
+++ b/system/gd/os/linux_generic/mgmt.cc
@@ -21,7 +21,7 @@
* This file will be replaced such that it is not optimized for now.
*/
-#include "hal/mgmt.h"
+#include "os/mgmt.h"
#include <bluetooth/log.h>
#include <poll.h>
@@ -33,7 +33,7 @@
extern int GetAdapterIndex();
namespace bluetooth {
-namespace hal {
+namespace os {
#define RETRY_ON_INTR(fn) \
do { \
@@ -80,7 +80,7 @@
* or failures in writing/reading the MGMT socket, the return opcode would
* be HCI_OP_NOP (0x0000).
*/
-uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) {
+uint16_t Management::getVendorSpecificCode(uint16_t vendor_specification) {
int hci = GetAdapterIndex();
int fd = btsocket_open_mgmt();
uint16_t ret_opcode = HCI_OP_NOP;
@@ -140,7 +140,7 @@
log::error("Failed to read mgmt socket: {}", -errno);
close(fd);
return ret_opcode;
- } else if (ret == 0) { // unlikely to happen, just a safeguard.
+ } else if (ret == 0) { // unlikely to happen, just a safeguard.
log::error("Failed to read mgmt socket: EOF");
close(fd);
return ret_opcode;
@@ -173,5 +173,5 @@
return ret_opcode;
}
-} // namespace hal
+} // namespace os
} // namespace bluetooth
diff --git a/system/gd/hal/mgmt.h b/system/gd/os/mgmt.h
similarity index 76%
rename from system/gd/hal/mgmt.h
rename to system/gd/os/mgmt.h
index 35b22cc..3b039b6 100644
--- a/system/gd/hal/mgmt.h
+++ b/system/gd/os/mgmt.h
@@ -21,7 +21,7 @@
#include <inttypes.h>
namespace bluetooth {
-namespace hal {
+namespace os {
#define HCI_OP_NOP 0x0000
@@ -56,10 +56,31 @@
#define MGMT_POLL_TIMEOUT_MS 2000
// This class provides an interface to interact with the kernel.
-class Mgmt {
+class Management {
public:
- uint16_t get_vs_opcode(uint16_t vendor_specification);
+ ~Management() = default;
+
+ /**
+ * Get the instance of singleton
+ *
+ * @return Management&
+ */
+ static Management& getInstance() {
+ static Management mgmt;
+ return mgmt;
+ }
+
+ uint16_t getVendorSpecificCode(uint16_t vendor_specification);
+
+protected:
+ // Singleton
+ Management() = default;
+
+private:
+ // delete copy constructor for singleton
+ Management(Management const&) = delete;
+ Management& operator=(Management const&) = delete;
};
-} // namespace hal
+} // namespace os
} // namespace bluetooth
diff --git a/system/gd/hal/mgmt_stub.cc b/system/gd/os/mgmt_stub.cc
similarity index 87%
rename from system/gd/hal/mgmt_stub.cc
rename to system/gd/os/mgmt_stub.cc
index 19a3a96..3088388 100644
--- a/system/gd/hal/mgmt_stub.cc
+++ b/system/gd/os/mgmt_stub.cc
@@ -22,15 +22,15 @@
#include <bluetooth/log.h>
-#include "hal/mgmt.h"
+#include "os/mgmt.h"
namespace bluetooth {
-namespace hal {
+namespace os {
-uint16_t Mgmt::get_vs_opcode(uint16_t vendor_specification) {
+uint16_t Management::getVendorSpecificCode(uint16_t vendor_specification) {
log::debug("Using stub for vendor opcode 0x{:04x}", vendor_specification);
return 0;
}
-} // namespace hal
+} // namespace os
} // namespace bluetooth
diff --git a/system/gd/rust/linux/mgmt/src/state_machine.rs b/system/gd/rust/linux/mgmt/src/state_machine.rs
index 2df9e7c..be4b796 100644
--- a/system/gd/rust/linux/mgmt/src/state_machine.rs
+++ b/system/gd/rust/linux/mgmt/src/state_machine.rs
@@ -946,6 +946,9 @@
/// Stop the adapter process.
///
+ /// This should block the thread until the btadapterd process is completely stopped,
+ /// that is, another btadapterd process with the same index is ready to be |start|.
+ ///
/// # Args
/// * `virtual_hci` - Virtual index of adapter used for apis.
/// * `real_hci` - Real index of the adapter on the system.
@@ -961,8 +964,7 @@
#[derive(Default)]
pub struct NativeInvoker {
- process_container: Option<Child>,
- bluetooth_pid: u32,
+ process_container: HashMap<VirtualHciIndex, Child>,
}
impl NativeInvoker {
@@ -973,23 +975,28 @@
impl ProcessManager for NativeInvoker {
fn start(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
- let new_process = Command::new("/usr/bin/btadapterd")
+ if self.process_container.contains_key(&virtual_hci) {
+ return;
+ }
+ match Command::new("/usr/bin/btadapterd")
.arg(format!("INDEX={} HCI={}", virtual_hci.to_i32(), real_hci.to_i32()))
.stdout(Stdio::piped())
.spawn()
- .expect("cannot open");
- self.bluetooth_pid = new_process.id();
- self.process_container = Some(new_process);
+ {
+ Ok(p) => {
+ self.process_container.insert(virtual_hci, p);
+ }
+ Err(e) => error!("Failed to start btadapterd: {}", e),
+ }
}
- fn stop(&mut self, _virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) {
- match self.process_container {
- Some(ref mut _p) => {
- signal::kill(Pid::from_raw(self.bluetooth_pid as i32), Signal::SIGTERM).unwrap();
- self.process_container = None;
+ fn stop(&mut self, virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) {
+ if let Some(mut p) = self.process_container.remove(&virtual_hci) {
+ if let Err(e) = signal::kill(Pid::from_raw(p.id() as i32), Signal::SIGTERM) {
+ warn!("Failed to send signal, process could have exited: {}", e);
}
- None => {
- warn!("Process doesn't exist");
- }
+ let _ = p.wait();
+ } else {
+ warn!("Process doesn't exist");
}
}
}
@@ -1018,14 +1025,14 @@
}
}
- fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
+ fn stop(&mut self, virtual_hci: VirtualHciIndex, _real_hci: RealHciIndex) {
+ // Currently in the upstart script, only INDEX is used for identifying the instance. Thus,
+ // intentionally NOT passing HCI to upstart, to avoid the following confusing situation:
+ // 1. UpstartInvoker: start btadapterd INDEX=0 HCI=0
+ // 2. Kernel: The HCI0 crashed, and became HCI1
+ // 3. UpstartInvoker: stop btadapterd INDEX=0 HCI=1 <---- This is confusing
if let Err(e) = Command::new("initctl")
- .args([
- "stop",
- "btadapterd",
- format!("INDEX={}", virtual_hci.to_i32()).as_str(),
- format!("HCI={}", real_hci.to_i32()).as_str(),
- ])
+ .args(["stop", "btadapterd", format!("INDEX={}", virtual_hci.to_i32()).as_str()])
.output()
{
error!("Failed to stop btadapterd: {}", e);
@@ -1055,6 +1062,9 @@
}
fn stop(&mut self, virtual_hci: VirtualHciIndex, real_hci: RealHciIndex) {
+ // FIXME(b/307625503): If the real index changed (could be caused by FW crash or USB issues)
+ // then this function would be broken. Need a re-design of the virtual/real index management
+ // that is compatible other invokers.
Command::new("systemctl")
.args([
"stop",
@@ -1530,11 +1540,30 @@
let restart_count =
self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0);
- // If we've restarted a number of times, attempt to use the reset mechanism instead
- // of retrying a start.
- if restart_count >= RESET_ON_RESTART_COUNT {
+ // This is an unexpectedly stop, which means the ProcessManager might not yet be
+ // ready to restart the same instance. Explicitly call stop to make sure we can move
+ // on to the next step.
+ warn!(
+ "{} stopped unexpectedly, first wait for the process to completely exit.",
+ hci
+ );
+ self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
+
+ if !present {
+ // If the index doesn't present, we have nothing to do - We can't even trigger
+ // the hardware reset because the sysfs reset entry would disappear as well.
+ // After the index presents, we shall try restarting.
+ warn!("{} exited. After {} restarts, index disappeared.", hci, restart_count);
+ self.modify_state(hci, |s: &mut AdapterState| {
+ s.state = ProcessState::Off;
+ s.restart_count = 0;
+ });
+ (ProcessState::Off, CommandTimeoutAction::CancelTimer)
+ } else if restart_count >= RESET_ON_RESTART_COUNT {
+ // If we've restarted a number of times, attempt to use the reset mechanism
+ // instead of retrying a start.
warn!(
- "{} stopped unexpectedly. After {} restarts, trying a reset recovery.",
+ "{} exited. After {} restarts, trying a reset recovery.",
hci, restart_count
);
// Reset the restart count since we're attempting a reset now.
@@ -1548,11 +1577,7 @@
self.reset_hci(real_hci);
(ProcessState::Off, CommandTimeoutAction::CancelTimer)
} else {
- warn!(
- "{} stopped unexpectedly, try restarting (attempt #{})",
- hci,
- restart_count + 1
- );
+ warn!("{} exited. Try restarting (attempt #{})", hci, restart_count + 1);
self.modify_state(hci, |s: &mut AdapterState| {
s.state = ProcessState::TurningOn;
s.restart_count += 1;
@@ -1599,12 +1624,30 @@
let restart_count =
self.get_state(hci, |a: &AdapterState| Some(a.restart_count)).unwrap_or(0);
- // If we've restarted a number of times, attempt to use the reset mechanism instead
- // of retrying a start.
- if restart_count >= RESET_ON_RESTART_COUNT {
+ // Explicitly call stop to make sure the ProcessManager is ready to restart the
+ // same instance.
+ warn!(
+ "{} timed out while starting, first wait for the process to completely exit.",
+ hci
+ );
+ self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
+
+ if !present {
+ // If the index doesn't present, we have nothing to do - We can't even trigger
+ // the hardware reset because the sysfs reset entry would disappear as well.
+ // After the index presents, we shall try restarting.
+ warn!("{} exited. After {} restarts, index disappeared.", hci, restart_count);
+ self.modify_state(hci, |s: &mut AdapterState| {
+ s.state = ProcessState::Off;
+ s.restart_count = 0;
+ });
+ StateMachineTimeoutActions::Noop
+ } else if restart_count >= RESET_ON_RESTART_COUNT {
+ // If we've restarted a number of times, attempt to use the reset mechanism
+ // instead of retrying a start.
warn!(
- "{} timed out while starting (present={}). After {} restarts, trying a reset recovery.",
- hci, present, restart_count
+ "{} exited. After {} restarts, trying a reset recovery.",
+ hci, restart_count
);
// Reset the restart count since we're attempting a reset now.
self.modify_state(hci, |s: &mut AdapterState| {
@@ -1617,17 +1660,11 @@
self.reset_hci(real_hci);
StateMachineTimeoutActions::Noop
} else {
- warn!(
- "{} timed out while starting (present={}), try restarting (attempt #{})",
- hci,
- present,
- restart_count + 1
- );
+ warn!("{} exited. Try restarting (attempt #{})", hci, restart_count + 1);
self.modify_state(hci, |s: &mut AdapterState| {
s.state = ProcessState::TurningOn;
s.restart_count += 1;
});
- self.process_manager.stop(hci, self.get_real_hci_by_virtual_id(hci));
self.process_manager.start(hci, self.get_real_hci_by_virtual_id(hci));
StateMachineTimeoutActions::RetryStart
}
@@ -1920,7 +1957,8 @@
tokio::runtime::Runtime::new().unwrap().block_on(async {
let mut process_manager = MockProcessManager::new();
process_manager.expect_start();
- // Expect to start again
+ // Expect to wait for stopped and start again
+ process_manager.expect_stop();
process_manager.expect_start();
let mut state_machine = make_state_machine(process_manager);
state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
@@ -1934,12 +1972,12 @@
assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
});
- // Stopped with no presence should restart if config enabled.
+ // Stopped with no presence should not restart even if config enabled.
tokio::runtime::Runtime::new().unwrap().block_on(async {
let mut process_manager = MockProcessManager::new();
process_manager.expect_start();
- // Expect to start again.
- process_manager.expect_start();
+ // Expect to wait for stopped
+ process_manager.expect_stop();
let mut state_machine = make_state_machine(process_manager);
state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
@@ -1948,9 +1986,9 @@
state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, false);
assert_eq!(
state_machine.action_on_bluetooth_stopped(DEFAULT_ADAPTER),
- (ProcessState::TurningOn, CommandTimeoutAction::ResetTimer)
+ (ProcessState::Off, CommandTimeoutAction::CancelTimer)
);
- assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
+ assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
});
// If floss was disabled and we see stopped, we shouldn't restart.
@@ -2084,7 +2122,6 @@
let mut process_manager = MockProcessManager::new();
process_manager.expect_start();
process_manager.expect_stop();
- process_manager.expect_start();
let mut state_machine = make_state_machine(process_manager);
state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, true);
state_machine.set_config_enabled(DEFAULT_ADAPTER, true);
@@ -2093,9 +2130,9 @@
state_machine.action_on_hci_presence_changed(DEFAULT_ADAPTER, false);
assert_eq!(
state_machine.action_on_command_timeout(DEFAULT_ADAPTER),
- StateMachineTimeoutActions::RetryStart
+ StateMachineTimeoutActions::Noop
);
- assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::TurningOn);
+ assert_eq!(state_machine.get_process_state(DEFAULT_ADAPTER), ProcessState::Off);
});
}
diff --git a/system/gd/rust/linux/stack/src/bluetooth_media.rs b/system/gd/rust/linux/stack/src/bluetooth_media.rs
index 4e6f6d2..1479df3 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_media.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_media.rs
@@ -1,8 +1,8 @@
//! Anything related to audio and media API.
use bt_topshim::btif::{
- BluetoothInterface, BtBondState, BtConnectionDirection, BtStatus, BtTransport, DisplayAddress,
- RawAddress, ToggleableProfile,
+ BluetoothInterface, BtBondState, BtStatus, BtTransport, DisplayAddress, RawAddress,
+ ToggleableProfile,
};
use bt_topshim::profiles::a2dp::{
A2dp, A2dpCallbacks, A2dpCallbacksDispatcher, A2dpCodecBitsPerSample, A2dpCodecChannelMode,
@@ -472,7 +472,8 @@
adapter: Arc<Mutex<Box<Bluetooth>>>,
a2dp: A2dp,
avrcp: Avrcp,
- avrcp_direction: BtConnectionDirection,
+ avrcp_address: Option<RawAddress>,
+ avrcp_states: HashMap<RawAddress, BtavConnectionState>,
a2dp_states: HashMap<RawAddress, BtavConnectionState>,
a2dp_audio_state: HashMap<RawAddress, BtavAudioState>,
a2dp_has_interrupted_stream: bool, // Only used for qualification.
@@ -548,7 +549,8 @@
adapter,
a2dp,
avrcp,
- avrcp_direction: BtConnectionDirection::Unknown,
+ avrcp_address: None,
+ avrcp_states: HashMap::new(),
a2dp_states: HashMap::new(),
a2dp_audio_state: HashMap::new(),
a2dp_has_interrupted_stream: false,
@@ -1307,6 +1309,31 @@
supported
);
+ // If is device initiated the AVRCP connection, emit a fake connecting state as
+ // stack don't receive one.
+ if self.avrcp_states.get(&addr) != Some(&BtavConnectionState::Connecting) {
+ metrics::profile_connection_state_changed(
+ addr,
+ Profile::AvrcpController as u32,
+ BtStatus::Success,
+ BtavConnectionState::Connecting as u32,
+ );
+ }
+ metrics::profile_connection_state_changed(
+ addr,
+ Profile::AvrcpController as u32,
+ BtStatus::Success,
+ BtavConnectionState::Connected as u32,
+ );
+ self.avrcp_states.insert(addr, BtavConnectionState::Connected);
+
+ if self.avrcp_address.is_some() {
+ warn!("Another AVRCP connection exists. Disconnect {}", DisplayAddress(&addr));
+ self.avrcp.disconnect(addr);
+ return;
+ }
+ self.avrcp_address = Some(addr);
+
match self.uinput.create(self.adapter_get_remote_name(addr), addr.to_string()) {
Ok(()) => info!("uinput device created for: {}", DisplayAddress(&addr)),
Err(e) => warn!("{}", e),
@@ -1325,46 +1352,14 @@
}
self.absolute_volume = supported;
-
- // If is device initiated the AVRCP connection, emit a fake connecting state as
- // stack don't receive one.
- if self.avrcp_direction != BtConnectionDirection::Outgoing {
- metrics::profile_connection_state_changed(
- addr,
- Profile::AvrcpController as u32,
- BtStatus::Success,
- BtavConnectionState::Connecting as u32,
- );
- }
- metrics::profile_connection_state_changed(
- addr,
- Profile::AvrcpController as u32,
- BtStatus::Success,
- BtavConnectionState::Connected as u32,
- );
- // Reset direction to unknown.
- self.avrcp_direction = BtConnectionDirection::Unknown;
-
self.add_connected_profile(addr, Profile::AvrcpController);
}
AvrcpCallbacks::AvrcpDeviceDisconnected(addr) => {
info!("[{}]: avrcp disconnected.", DisplayAddress(&addr));
- self.uinput.close(addr.to_string());
-
- // TODO: better support for multi-device
- self.absolute_volume = false;
-
- // This may be considered a critical profile in the extreme case
- // where only AVRCP was connected.
- let is_profile_critical = match self.connected_profiles.get(&addr) {
- Some(profiles) => *profiles == HashSet::from([Profile::AvrcpController]),
- None => false,
- };
-
// If the peer device initiated the AVRCP disconnection, emit a fake connecting
// state as stack don't receive one.
- if self.avrcp_direction != BtConnectionDirection::Outgoing {
+ if self.avrcp_states.get(&addr) != Some(&BtavConnectionState::Disconnecting) {
metrics::profile_connection_state_changed(
addr,
Profile::AvrcpController as u32,
@@ -1378,8 +1373,25 @@
BtStatus::Success,
BtavConnectionState::Disconnected as u32,
);
- // Reset direction to unknown.
- self.avrcp_direction = BtConnectionDirection::Unknown;
+ self.avrcp_states.remove(&addr);
+
+ if self.avrcp_address != Some(addr) {
+ // Ignore disconnection to address we don't care
+ return;
+ }
+ self.avrcp_address = None;
+
+ self.uinput.close(addr.to_string());
+
+ // TODO: better support for multi-device
+ self.absolute_volume = false;
+
+ // This may be considered a critical profile in the extreme case
+ // where only AVRCP was connected.
+ let is_profile_critical = match self.connected_profiles.get(&addr) {
+ Some(profiles) => *profiles == HashSet::from([Profile::AvrcpController]),
+ None => false,
+ };
self.rm_connected_profile(addr, Profile::AvrcpController, is_profile_critical);
}
@@ -3336,11 +3348,11 @@
BtStatus::Success,
BtavConnectionState::Connecting as u32,
);
- self.avrcp_direction = BtConnectionDirection::Outgoing;
+ self.avrcp_states.insert(addr, BtavConnectionState::Connecting);
let status = self.avrcp.connect(addr);
if BtStatus::Success != status {
// Reset direction to unknown.
- self.avrcp_direction = BtConnectionDirection::Unknown;
+ self.avrcp_states.remove(&addr);
metrics::profile_connection_state_changed(
addr,
Profile::AvrcpController as u32,
@@ -3463,11 +3475,11 @@
BtStatus::Success,
BtavConnectionState::Disconnecting as u32,
);
- self.avrcp_direction = BtConnectionDirection::Outgoing;
+ self.avrcp_states.insert(addr, BtavConnectionState::Disconnecting);
let status = self.avrcp.disconnect(addr);
if BtStatus::Success != status {
// Reset direction to unknown.
- self.avrcp_direction = BtConnectionDirection::Unknown;
+ self.avrcp_states.remove(&addr);
metrics::profile_connection_state_changed(
addr,
Profile::AvrcpController as u32,
@@ -3569,6 +3581,10 @@
}
fn set_volume(&mut self, volume: u8) {
+ if self.avrcp_address.is_none() {
+ return;
+ }
+
// Guard the range 0-127 by the try_from cast from u8 to i8.
let vol = match i8::try_from(volume) {
Ok(val) => val,
@@ -3578,7 +3594,7 @@
}
};
- self.avrcp.set_volume(vol);
+ self.avrcp.set_volume(self.avrcp_address.unwrap(), vol);
}
fn set_hfp_volume(&mut self, volume: u8, addr: RawAddress) {
diff --git a/system/gd/rust/topshim/Android.bp b/system/gd/rust/topshim/Android.bp
index af5ed8c..fe3a5cc 100644
--- a/system/gd/rust/topshim/Android.bp
+++ b/system/gd/rust/topshim/Android.bp
@@ -66,11 +66,18 @@
],
host_supported: true,
static_libs: [
+ "aics",
"libbluetooth_hci_pdl",
"libbluetooth_log",
"libchrome",
"libflatbuffers-cpp",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
+ shared_libs: [
+ "libbinder",
+ ],
target: {
darwin: {
enabled: false,
diff --git a/system/gd/rust/topshim/BUILD.gn b/system/gd/rust/topshim/BUILD.gn
index a20dbee..b2c937d 100644
--- a/system/gd/rust/topshim/BUILD.gn
+++ b/system/gd/rust/topshim/BUILD.gn
@@ -50,9 +50,11 @@
]
deps = [
":btif_bridge_header",
+ "//bt/system/bta/aics:aics",
"//bt/system/pdl:BluetoothGeneratedPackets_h",
]
configs = [
+ "//bt/system/bta/aics:aics_defaults",
"//bt/system/gd:gd_defaults",
"//bt/system/log:log_defaults",
]
@@ -82,6 +84,9 @@
"//bt/system/gd:gd_defaults",
"//bt/system/log:log_defaults",
]
+ include_dirs = [
+ "//bt/system/bta/aics/include",
+ ]
}
cxxbridge_libheader("cxxlibheader") {
diff --git a/system/gd/rust/topshim/btav/btav_shim.cc b/system/gd/rust/topshim/btav/btav_shim.cc
index 2723d53..3838d03 100644
--- a/system/gd/rust/topshim/btav/btav_shim.cc
+++ b/system/gd/rust/topshim/btav/btav_shim.cc
@@ -17,6 +17,7 @@
#include "rust/topshim/btav/btav_shim.h"
#include <cstdio>
+#include <map>
#include <memory>
#include "base/functional/callback.h"
@@ -156,12 +157,12 @@
}
void DeviceConnected(const RawAddress& addr, VolumeChangedCb cb) override {
- volumeCb = std::move(cb);
+ volumeCbs[addr] = std::move(cb);
rusty::avrcp_device_connected(addr, /*absolute_volume_enabled=*/true);
}
void DeviceDisconnected(const RawAddress& addr) override {
- volumeCb.Reset();
+ volumeCbs.erase(addr);
rusty::avrcp_device_disconnected(addr);
}
@@ -175,16 +176,19 @@
}
// Set CT's (headsets, speakers) volume.
- void SetDeviceVolume(int8_t volume) {
- if (!volumeCb || volume < 0) {
+ void SetDeviceVolume(const RawAddress& addr, int8_t volume) {
+ if (volume < 0) {
return;
}
- volumeCb.Run(volume);
+ const auto& cb_iter = this->volumeCbs.find(addr);
+ if (cb_iter != this->volumeCbs.end()) {
+ cb_iter->second.Run(volume);
+ }
}
private:
- VolumeInterface::VolumeChangedCb volumeCb;
+ std::map<RawAddress, VolumeInterface::VolumeChangedCb> volumeCbs;
};
} // namespace bluetooth::avrcp
@@ -288,10 +292,16 @@
}
int A2dpIntf::init() const {
- std::vector<btav_a2dp_codec_config_t> a;
+ btav_a2dp_codec_config_t a2dp_config_sbc{
+ .codec_type = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,
+ .codec_priority = BTAV_A2DP_CODEC_PRIORITY_HIGHEST,
+ // Using default settings for those untouched fields
+ };
+
+ std::vector<btav_a2dp_codec_config_t> codec_priorities(1, a2dp_config_sbc);
std::vector<btav_a2dp_codec_config_t> b;
std::vector<btav_a2dp_codec_info_t> c;
- return btif_av_source_init(&internal::g_callbacks, 1, a, b, &c);
+ return btif_av_source_init(&internal::g_callbacks, 1, codec_priorities, b, &c);
}
uint32_t A2dpIntf::connect(RawAddress addr) const { return btif_av_source_connect(addr); }
@@ -362,7 +372,9 @@
uint32_t AvrcpIntf::connect(RawAddress addr) { return intf_->ConnectDevice(addr); }
uint32_t AvrcpIntf::disconnect(RawAddress addr) { return intf_->DisconnectDevice(addr); }
-void AvrcpIntf::set_volume(int8_t volume) { return mVolumeInterface.SetDeviceVolume(volume); }
+void AvrcpIntf::set_volume(RawAddress addr, int8_t volume) {
+ return mVolumeInterface.SetDeviceVolume(addr, volume);
+}
void AvrcpIntf::set_playback_status(const ::rust::String& status) {
avrcp::PlayState state = avrcp::PlayState::STOPPED;
diff --git a/system/gd/rust/topshim/btav/btav_shim.h b/system/gd/rust/topshim/btav/btav_shim.h
index 6482bca..f32fb24 100644
--- a/system/gd/rust/topshim/btav/btav_shim.h
+++ b/system/gd/rust/topshim/btav/btav_shim.h
@@ -67,7 +67,7 @@
uint32_t disconnect(RawAddress addr);
// interface for Audio server
- void set_volume(int8_t volume);
+ void set_volume(RawAddress addr, int8_t volume);
void set_playback_status(const ::rust::String& status);
void set_position(int64_t position_us);
diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp
index 725ddaa..505d5e8 100644
--- a/system/gd/rust/topshim/facade/Android.bp
+++ b/system/gd/rust/topshim/facade/Android.bp
@@ -32,6 +32,7 @@
"libtokio",
],
static_libs: [
+ "aics",
"avrcp-target-service",
"lib-bt-packets",
"lib-bt-packets-avrcp",
@@ -72,6 +73,7 @@
],
shared_libs: [
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libcrypto",
"libcutils",
"libgrpc++",
diff --git a/system/gd/rust/topshim/src/profiles/avrcp.rs b/system/gd/rust/topshim/src/profiles/avrcp.rs
index 16039a1..1b63ef5 100644
--- a/system/gd/rust/topshim/src/profiles/avrcp.rs
+++ b/system/gd/rust/topshim/src/profiles/avrcp.rs
@@ -38,7 +38,7 @@
fn cleanup(self: Pin<&mut AvrcpIntf>);
fn connect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u32;
fn disconnect(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress) -> u32;
- fn set_volume(self: Pin<&mut AvrcpIntf>, volume: i8);
+ fn set_volume(self: Pin<&mut AvrcpIntf>, bt_addr: RawAddress, volume: i8);
fn set_playback_status(self: Pin<&mut AvrcpIntf>, status: &String);
fn set_position(self: Pin<&mut AvrcpIntf>, position_us: i64);
fn set_metadata(
@@ -173,8 +173,8 @@
}
#[profile_enabled_or]
- pub fn set_volume(&mut self, volume: i8) {
- self.internal.pin_mut().set_volume(volume);
+ pub fn set_volume(&mut self, addr: RawAddress, volume: i8) {
+ self.internal.pin_mut().set_volume(addr, volume);
}
#[profile_enabled_or(false)]
diff --git a/system/gd/rust/topshim/vc/vc_shim.cc b/system/gd/rust/topshim/vc/vc_shim.cc
index f7f68d5..da0e055 100644
--- a/system/gd/rust/topshim/vc/vc_shim.cc
+++ b/system/gd/rust/topshim/vc/vc_shim.cc
@@ -21,6 +21,7 @@
#include <string>
+#include "aics/api.h"
#include "src/profiles/vc.rs.h"
#include "types/raw_address.h"
@@ -135,10 +136,11 @@
topshim::rust::internal::ext_audio_out_description_cb(address, ext_output_id, descr);
}
- void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id, int8_t gain_val,
- uint8_t gain_mode_auto, bool mute) {
- log::info("address={}, ext_input_id={}, gain_val={}, gain_mode_auto={}, mute={}", address,
- ext_input_id, gain_val, gain_mode_auto, mute);
+ void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id,
+ int8_t gain_setting, bluetooth::aics::Mute mute,
+ uint8_t gain_mode_auto) {
+ log::info("address={}, ext_input_id={}, gain_setting={}, gain_mode_auto={}, mute={}", address,
+ ext_input_id, gain_setting, gain_mode_auto, static_cast<uint8_t>(mute));
log::info("Not implemented");
}
diff --git a/system/include/Android.bp b/system/include/Android.bp
index f76b6fc..5540d0dd 100644
--- a/system/include/Android.bp
+++ b/system/include/Android.bp
@@ -35,11 +35,13 @@
"//vendor:__subpackages__",
],
header_libs: [
+ "aics_headers",
"avrcp_headers",
"libbluetooth-types-header",
"libbtcore_headers",
],
export_header_lib_headers: [
+ "aics_headers",
"avrcp_headers",
"libbluetooth-types-header",
"libbtcore_headers",
diff --git a/system/include/hardware/bt_has.h b/system/include/hardware/bt_has.h
index 631ca65..c5e1744 100644
--- a/system/include/hardware/bt_has.h
+++ b/system/include/hardware/bt_has.h
@@ -26,6 +26,7 @@
namespace has {
/** Connection State */
+// Must be kept in sync with BluetoothProfile.java
enum class ConnectionState : uint8_t {
DISCONNECTED = 0,
CONNECTING,
diff --git a/system/include/hardware/bt_vc.h b/system/include/hardware/bt_vc.h
index 7d24a07..5e258b5 100644
--- a/system/include/hardware/bt_vc.h
+++ b/system/include/hardware/bt_vc.h
@@ -17,6 +17,7 @@
#pragma once
+#include <aics/api.h>
#include <hardware/bluetooth.h>
#include <raw_address.h>
@@ -26,6 +27,8 @@
namespace bluetooth {
namespace vc {
+using bluetooth::aics::Mute;
+
// Must be kept in sync with BluetoothProfile.java
enum class ConnectionState { DISCONNECTED = 0, CONNECTING, CONNECTED, DISCONNECTING };
@@ -73,7 +76,7 @@
/* Callbacks for Audio Input Stream (AIS) - Extended Audio Inputs */
virtual void OnExtAudioInStateChanged(const RawAddress& address, uint8_t ext_input_id,
- int8_t gain_val, uint8_t gain_mode_auto, bool mute) = 0;
+ int8_t gain_setting, Mute mute, uint8_t gain_mode_auto) = 0;
virtual void OnExtAudioInStatusChanged(const RawAddress& address, uint8_t ext_input_id,
VolumeInputStatus status) = 0;
@@ -131,8 +134,8 @@
virtual void GetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id) = 0;
virtual void SetExtAudioInDescription(const RawAddress& address, uint8_t ext_input_id,
std::string descr) = 0;
- virtual void SetExtAudioInGainValue(const RawAddress& address, uint8_t ext_input_id,
- int8_t value) = 0;
+ virtual void SetExtAudioInGainSetting(const RawAddress& address, uint8_t ext_input_id,
+ int8_t gain_setting) = 0;
virtual void SetExtAudioInGainMode(const RawAddress& address, uint8_t ext_input_id,
bool automatic) = 0;
virtual void SetExtAudioInGainMute(const RawAddress& address, uint8_t ext_input_id,
diff --git a/system/main/Android.bp b/system/main/Android.bp
index cfa85ee..5b27092 100644
--- a/system/main/Android.bp
+++ b/system/main/Android.bp
@@ -215,9 +215,13 @@
"liblog",
"libosi",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libPlatformProperties",
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libbinder_ndk",
"libcrypto",
"server_configurable_flags",
diff --git a/system/profile/avrcp/device.cc b/system/profile/avrcp/device.cc
index 7c4b6b3..3167363 100644
--- a/system/profile/avrcp/device.cc
+++ b/system/profile/avrcp/device.cc
@@ -1365,6 +1365,7 @@
auto no_items_rsp = GetFolderItemsResponseBuilder::MakePlayerListBuilder(
Status::RANGE_OUT_OF_BOUNDS, 0x0000, browse_mtu_);
send_message(label, true, std::move(no_items_rsp));
+ return;
}
auto builder = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::NO_ERROR, 0x0000,
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index cb987de..aebe1e7 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -1214,7 +1214,11 @@
"avct/avct_lcb_act.cc",
"test/stack_avctp_test.cc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libcrypto",
"libcutils",
"server_configurable_flags",
@@ -1284,7 +1288,11 @@
"test/common/mock_stack_avdt_msg.cc",
"test/stack_avdtp_test.cc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libcrypto",
"libcutils",
"server_configurable_flags",
@@ -1392,7 +1400,11 @@
"test/a2dp/wav_reader.cc",
"test/a2dp/wav_reader_unittest.cc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libcrypto",
"libcutils",
"libprotobuf-cpp-lite",
@@ -1449,7 +1461,11 @@
"test/a2dp/a2dp_vendor_ldac_decoder_test.cc",
"test/a2dp/misc_fake.cc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libcrypto",
"libcutils",
],
@@ -1506,8 +1522,12 @@
"test/gatt/mock_gatt_utils_ref.cc",
"test/stack_gatt_sr_hash_test.cc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libcrypto",
"libcutils",
"server_configurable_flags",
@@ -1797,8 +1817,12 @@
"libprotobuf-cpp-lite",
"libudrv-uipc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libcrypto",
"libcutils",
"server_configurable_flags",
@@ -1986,7 +2010,11 @@
"libosi",
"server_configurable_flags",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
+ "libbinder",
"libbinder_ndk",
"libcrypto",
],
@@ -2077,9 +2105,13 @@
"libprotobuf-cpp-lite",
"libstatslog_bt",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"libbinder_ndk",
"libcrypto",
"libcutils",
@@ -2169,9 +2201,13 @@
"libprotobuf-cpp-lite",
"libstatslog_bt",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"libbinder_ndk",
"libcrypto",
"libcutils",
@@ -2263,9 +2299,13 @@
"libosi",
"libstatslog_bt",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"libbinder_ndk",
"libcrypto",
"server_configurable_flags",
@@ -2367,8 +2407,12 @@
"libprotobuf-cpp-lite",
"libudrv-uipc",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libcrypto",
"libcutils",
"server_configurable_flags",
@@ -2432,8 +2476,12 @@
"libgmock",
"liblog",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libcrypto",
"libcutils",
"server_configurable_flags",
diff --git a/system/stack/acl/ble_acl.cc b/system/stack/acl/ble_acl.cc
index 0606716..683e480 100644
--- a/system/stack/acl/ble_acl.cc
+++ b/system/stack/acl/ble_acl.cc
@@ -27,14 +27,13 @@
#include "stack/btm/btm_sec.h"
#include "stack/connection_manager/connection_manager.h"
#include "stack/include/acl_api.h"
+#include "stack/include/ble_acl_interface.h"
#include "stack/include/btm_ble_addr.h"
#include "stack/include/btm_ble_privacy.h"
+#include "stack/include/gatt_api.h"
#include "stack/include/l2cap_hci_link_interface.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
extern tBTM_CB btm_cb;
@@ -144,8 +143,6 @@
btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, &address_with_type.bda, status);
}
-void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval, uint16_t latency,
- uint16_t timeout, tHCI_STATUS status);
void acl_ble_update_event_received(tHCI_STATUS status, uint16_t handle, uint16_t interval,
uint16_t latency, uint16_t timeout) {
l2cble_process_conn_update_evt(handle, status, interval, latency, timeout);
diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc
index 0c52e80..fecf7b9 100644
--- a/system/stack/acl/btm_acl.cc
+++ b/system/stack/acl/btm_acl.cc
@@ -73,6 +73,7 @@
#include "stack/include/btm_status.h"
#include "stack/include/hci_error_code.h"
#include "stack/include/hcimsgs.h"
+#include "stack/include/inq_hci_link_interface.h"
#include "stack/include/l2cap_acl_interface.h"
#include "stack/include/l2cdefs.h"
#include "stack/include/main_thread.h"
@@ -88,9 +89,6 @@
#define PROPERTY_AUTO_FLUSH_TIMEOUT "bluetooth.core.classic.auto_flush_timeout"
#endif
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
using bluetooth::legacy::hci::GetInterface;
@@ -212,27 +210,6 @@
p_acl.rs_disc_pending = BTM_SEC_RS_PENDING;
}
-void hci_btm_set_link_supervision_timeout(tACL_CONN& link, uint16_t timeout) {
- if (link.link_role != HCI_ROLE_CENTRAL) {
- /* Only send if current role is Central; 2.0 spec requires this */
- log::warn("Can only set link supervision timeout if central role:{}", RoleText(link.link_role));
- return;
- }
-
- if (!bluetooth::shim::GetController()->IsSupported(
- bluetooth::hci::OpCode::WRITE_LINK_SUPERVISION_TIMEOUT)) {
- log::warn(
- "UNSUPPORTED by controller write link supervision timeout:{:.2f}ms "
- "bd_addr:{}",
- supervision_timeout_to_seconds(timeout), link.RemoteAddress());
- return;
- }
- log::debug("Setting link supervision timeout:{:.2f}s peer:{}", double(timeout) * 0.01,
- link.RemoteAddress());
- link.link_super_tout = timeout;
- btsnd_hcic_write_link_super_tout(link.Handle(), timeout);
-}
-
/* 3 seconds timeout waiting for responses */
#define BTM_DEV_REPLY_TIMEOUT_MS (3 * 1000)
@@ -302,10 +279,6 @@
return nullptr;
}
-tACL_CONN* acl_get_connection_from_address(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
- return internal_.btm_bda_to_acl(bd_addr, transport);
-}
-
void StackAclBtmAcl::btm_acl_consolidate(const RawAddress& identity_addr, const RawAddress& rpa) {
tACL_CONN* p_acl = &btm_cb.acl_cb_.acl_db[0];
for (uint8_t index = 0; index < MAX_L2CAP_LINKS; index++, p_acl++) {
@@ -356,7 +329,7 @@
return &btm_cb.acl_cb_.acl_db[index];
}
-tACL_CONN* acl_get_connection_from_handle(uint16_t handle) {
+static tACL_CONN* acl_get_connection_from_handle(uint16_t handle) {
return internal_.acl_get_connection_from_handle(handle);
}
@@ -803,8 +776,9 @@
btm_iot_save_remote_versions(p_acl_cb);
}
-void btm_process_remote_version_complete(uint8_t status, uint16_t handle, uint8_t lmp_version,
- uint16_t manufacturer, uint16_t lmp_subversion) {
+static void btm_process_remote_version_complete(uint8_t status, uint16_t handle,
+ uint8_t lmp_version, uint16_t manufacturer,
+ uint16_t lmp_subversion) {
tACL_CONN* p_acl_cb = internal_.acl_get_connection_from_handle(handle);
if (p_acl_cb == nullptr) {
log::warn("Received remote version complete for unknown acl");
@@ -2376,7 +2350,7 @@
// 7.1.6 Disconnect command
// Only a subset of reasons are valid and will be accepted
// by the controller
-bool is_disconnect_reason_valid(const tHCI_REASON& reason) {
+static bool is_disconnect_reason_valid(const tHCI_REASON& reason) {
switch (reason) {
case HCI_ERR_AUTH_FAILURE:
case HCI_ERR_PEER_USER:
diff --git a/system/stack/acl/btm_pm.cc b/system/stack/acl/btm_pm.cc
index c34e776..1914f30 100644
--- a/system/stack/acl/btm_pm.cc
+++ b/system/stack/acl/btm_pm.cc
@@ -44,19 +44,17 @@
#include "main/shim/entry.h"
#include "osi/include/stack_power_telemetry.h"
#include "stack/btm/btm_int_types.h"
+#include "stack/include/acl_api.h"
+#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/bt_types.h"
#include "stack/include/btm_log_history.h"
#include "stack/include/btm_status.h"
+#include "stack/include/l2cap_hci_link_interface.h"
+#include "stack/include/sco_hci_link_interface.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
-void l2c_OnHciModeChangeSendPendingPackets(RawAddress remote);
-void btm_sco_chk_pend_unpark(tHCI_STATUS status, uint16_t handle);
-void btm_cont_rswitch_from_handle(uint16_t hci_handle);
extern tBTM_CB btm_cb;
namespace {
@@ -750,8 +748,8 @@
* Returns none.
*
******************************************************************************/
-void process_ssr_event(tHCI_STATUS status, uint16_t handle, uint16_t /* max_tx_lat */,
- uint16_t max_rx_lat) {
+static void process_ssr_event(tHCI_STATUS status, uint16_t handle, uint16_t /* max_tx_lat */,
+ uint16_t max_rx_lat) {
if (pm_mode_db.count(handle) == 0) {
log::warn("Received sniff subrating event with no active ACL");
return;
diff --git a/system/stack/avct/avct_api.cc b/system/stack/avct/avct_api.cc
index 7e1e7a9..55c7cd0 100644
--- a/system/stack/avct/avct_api.cc
+++ b/system/stack/avct/avct_api.cc
@@ -113,8 +113,9 @@
// Clean up AVCTP data structures
for (int i = 0; i < AVCT_NUM_LINKS; i++) {
- osi_free(avct_cb.lcb[i].p_rx_msg);
+ osi_free_and_reset((void**)&(avct_cb.lcb[i].p_rx_msg));
fixed_queue_free(avct_cb.lcb[i].tx_q, nullptr);
+ avct_cb.lcb[i].tx_q = nullptr;
osi_free_and_reset((void**)&(avct_cb.bcb[i].p_tx_msg));
}
}
diff --git a/system/stack/avct/avct_lcb.cc b/system/stack/avct/avct_lcb.cc
index ac4519c..43a2b94 100644
--- a/system/stack/avct/avct_lcb.cc
+++ b/system/stack/avct/avct_lcb.cc
@@ -327,7 +327,7 @@
// If not, de-allocate now...
log::verbose("Freeing LCB");
- osi_free(p_lcb->p_rx_msg);
+ osi_free_and_reset((void**)&(p_lcb->p_rx_msg));
fixed_queue_free(p_lcb->tx_q, NULL);
memset(p_lcb, 0, sizeof(tAVCT_LCB));
}
diff --git a/system/stack/avrc/avrc_api.cc b/system/stack/avrc/avrc_api.cc
index 28f6f85..ea82921 100644
--- a/system/stack/avrc/avrc_api.cc
+++ b/system/stack/avrc/avrc_api.cc
@@ -82,6 +82,8 @@
#define AVRC_MSG_MASK_IS_VENDOR_CMD 0x01
#define AVRC_MSG_MASK_IS_CONTINUATION_RSP 0x02
+static void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask);
+
/******************************************************************************
*
* Function avrcp_absolute_volume_is_enabled
@@ -216,14 +218,19 @@
* Returns Nothing.
*
*****************************************************************************/
-void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask) {
+static void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask) {
+ if (!avrc_cb.ccb_int[handle].tle) {
+ log::warn("Unable to start response timer handle=0x{:02x} label=0x{:02x} msg_mask:0x{:02x}",
+ handle, label, msg_mask);
+ return;
+ }
+
tAVRC_PARAM* param = static_cast<tAVRC_PARAM*>(osi_malloc(sizeof(tAVRC_PARAM)));
param->handle = handle;
param->label = label;
param->msg_mask = msg_mask;
- log::verbose("AVRC: starting timer (handle=0x{:02x}, label=0x{:02x})", handle, label);
-
+ log::verbose("AVRC: starting timer (handle=0x{:02x} label=0x{:02x})", handle, label);
alarm_set_on_mloop(avrc_cb.ccb_int[handle].tle, AVRC_CMD_TOUT_MS, avrc_process_timeout, param);
}
diff --git a/system/stack/avrc/avrc_int.h b/system/stack/avrc/avrc_int.h
index 3394bb1..cf3a0de 100644
--- a/system/stack/avrc/avrc_int.h
+++ b/system/stack/avrc/avrc_int.h
@@ -159,7 +159,6 @@
uint8_t avrc_opcode_from_pdu(uint8_t pdu);
bool avrc_is_valid_opcode(uint8_t opcode);
void avrc_flush_cmd_q(uint8_t handle);
-void avrc_start_cmd_timer(uint8_t handle, uint8_t label, uint8_t msg_mask);
void avrc_send_next_vendor_cmd(uint8_t handle);
#endif /* AVRC_INT_H */
diff --git a/system/stack/btm/btm_dev.cc b/system/stack/btm/btm_dev.cc
index cdc7e27..c791c03 100644
--- a/system/stack/btm/btm_dev.cc
+++ b/system/stack/btm/btm_dev.cc
@@ -45,6 +45,7 @@
#include "stack/include/btm_ble_privacy.h"
#include "stack/include/btm_client_interface.h"
#include "stack/include/btm_log_history.h"
+#include "stack/include/gatt_api.h"
#include "stack/include/l2cap_interface.h"
#include "types/raw_address.h"
@@ -54,7 +55,6 @@
using namespace bluetooth;
extern tBTM_CB btm_cb;
-void gatt_consolidate(const RawAddress& identity_addr, const RawAddress& rpa);
namespace {
diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc
index d22fba7..953487b 100644
--- a/system/stack/btm/btm_devctl.cc
+++ b/system/stack/btm/btm_devctl.cc
@@ -41,6 +41,7 @@
#include "stack/connection_manager/connection_manager.h"
#include "stack/include/acl_api.h"
#include "stack/include/acl_api_types.h"
+#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/bt_types.h"
#include "stack/include/btm_ble_privacy.h"
#include "stack/include/btm_inq.h"
@@ -57,7 +58,6 @@
extern tBTM_CB btm_cb;
void btm_inq_db_reset(void);
-void btm_pm_reset(void);
/******************************************************************************/
/* L O C A L D A T A D E F I N I T I O N S */
/******************************************************************************/
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index e647715..dc7ba92 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -1566,22 +1566,27 @@
"enc: x{:x}",
p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED,
p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED);
- /* SM4, but we do not know for sure which level of security we need.
- * as long as we have a link key, it's OK */
- if ((0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED)) ||
- (0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED))) {
- rc = tBTM_STATUS::BTM_DELAY_CHECK;
- /*
- 2046 may report HCI_Encryption_Change and L2C Connection Request out of
- sequence
- because of data path issues. Delay this disconnect a little bit
- */
- log::info("peer should have initiated security process by now (SM4 to SM4)");
- p_dev_rec->sec_rec.p_callback = p_callback;
- p_dev_rec->sec_rec.classic_link = tSECURITY_STATE::DELAY_FOR_ENC;
- (*p_callback)(bd_addr, transport, p_ref_data, rc);
- return tBTM_STATUS::BTM_SUCCESS;
+ if (!com::android::bluetooth::flags::trigger_sec_proc_on_inc_access_req()) {
+ /* SM4, but we do not know for sure which level of security we need.
+ * as long as we have a link key, it's OK */
+ if ((0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED)) ||
+ (0 == (p_dev_rec->sec_rec.sec_flags & BTM_SEC_ENCRYPTED))) {
+ rc = tBTM_STATUS::BTM_DELAY_CHECK;
+ /*
+ 2046 may report HCI_Encryption_Change and L2C Connection Request out of
+ sequence
+ because of data path issues. Delay this disconnect a little bit
+ */
+ log::info("peer should have initiated security process by now (SM4 to SM4)");
+ p_dev_rec->sec_rec.p_callback = p_callback;
+ p_dev_rec->sec_rec.classic_link = tSECURITY_STATE::DELAY_FOR_ENC;
+ (*p_callback)(bd_addr, transport, p_ref_data, rc);
+
+ return tBTM_STATUS::BTM_SUCCESS;
+ }
+ } else {
+ log::debug("force fallthrough to trigger sec proceudure");
}
}
@@ -2159,7 +2164,7 @@
BTM_LogHistory(
kBtmLogTag, (p_bd_addr) ? *p_bd_addr : RawAddress::kEmpty, "RNR complete",
base::StringPrintf("hci_status:%s name:%s", hci_error_code_text(hci_status).c_str(),
- PRIVATE_NAME(p_bd_name)));
+ PRIVATE_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
@@ -3424,9 +3429,6 @@
btm_sec_encrypt_change(handle, static_cast<tHCI_STATUS>(status), 1 /* enable */, key_size);
}
-// TODO: Remove
-void smp_cancel_start_encryption_attempt();
-
/*******************************************************************************
*
* Function btm_encryption_change_evt
diff --git a/system/stack/btm/security_device_record.h b/system/stack/btm/security_device_record.h
index c1037a4..6dc0cfa 100644
--- a/system/stack/btm/security_device_record.h
+++ b/system/stack/btm/security_device_record.h
@@ -338,8 +338,8 @@
"sec_prop:%s",
ADDRESS_TO_LOGGABLE_CSTR(bd_addr), DeviceTypeText(device_type).c_str(),
dev_class_text(dev_class).c_str(), remote_version_info.ToString().c_str(), sm4,
- (remote_supports_secure_connections) ? 'T' : 'F', PRIVATE_NAME(sec_bd_name),
- sec_rec.ToString().c_str());
+ (remote_supports_secure_connections) ? 'T' : 'F',
+ PRIVATE_NAME(reinterpret_cast<char const*>(sec_bd_name)), sec_rec.ToString().c_str());
}
public:
diff --git a/system/stack/btu/btu_hcif.cc b/system/stack/btu/btu_hcif.cc
index f184626..9dc7d98 100644
--- a/system/stack/btu/btu_hcif.cc
+++ b/system/stack/btu/btu_hcif.cc
@@ -55,6 +55,7 @@
#include "stack/include/main_thread.h"
#include "stack/include/sco_hci_link_interface.h"
#include "stack/include/sec_hci_link_interface.h"
+#include "stack/include/smp_api.h"
#include "stack/include/stack_metrics_logging.h"
#include "types/hci_role.h"
#include "types/raw_address.h"
@@ -68,7 +69,6 @@
bool BTM_BLE_IS_RESOLVE_BDA(const RawAddress& x); // TODO remove
void BTA_sys_signal_hw_error(); // TODO remove
-void smp_cancel_start_encryption_attempt(); // TODO remove
void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason,
std::string comment); // TODO remove
diff --git a/system/stack/fuzzers/l2cap_fuzzer.cc b/system/stack/fuzzers/l2cap_fuzzer.cc
index 2c5c3d2..1963983 100644
--- a/system/stack/fuzzers/l2cap_fuzzer.cc
+++ b/system/stack/fuzzers/l2cap_fuzzer.cc
@@ -85,7 +85,7 @@
const std::string SnoopLogger::kBtSnoopLogModeFiltered = "filtered";
-std::string SnoopLogger::GetBtSnoopMode() { return "filtered"; }
+std::string SnoopLogger::GetCurrentSnoopMode() { return "filtered"; }
void SnoopLogger::AcceptlistL2capChannel(uint16_t, uint16_t, uint16_t) {}
void SnoopLogger::AddA2dpMediaChannel(uint16_t, uint16_t, uint16_t) {}
void SnoopLogger::AddRfcommL2capChannel(uint16_t, uint16_t, uint16_t) {}
diff --git a/system/stack/gap/gap_ble.cc b/system/stack/gap/gap_ble.cc
index 92c826a..a97a8ca 100644
--- a/system/stack/gap/gap_ble.cc
+++ b/system/stack/gap/gap_ble.cc
@@ -23,6 +23,7 @@
#include <queue>
#include "gap_api.h"
+#include "gap_int.h"
#include "gatt_api.h"
#include "hardware/bt_gatt_types.h"
#include "stack/include/bt_types.h"
@@ -33,9 +34,6 @@
#include "types/bt_transport.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using bluetooth::Uuid;
using namespace bluetooth;
@@ -61,10 +59,10 @@
tGAP_BLE_ATTR_VALUE attr_value;
} tGAP_ATTR;
-void server_attr_request_cback(tCONN_ID, uint32_t, tGATTS_REQ_TYPE, tGATTS_DATA*);
-void client_connect_cback(tGATT_IF, const RawAddress&, tCONN_ID, bool, tGATT_DISCONN_REASON,
- tBT_TRANSPORT);
-void client_cmpl_cback(tCONN_ID, tGATTC_OPTYPE, tGATT_STATUS, tGATT_CL_COMPLETE*);
+static void server_attr_request_cback(tCONN_ID, uint32_t, tGATTS_REQ_TYPE, tGATTS_DATA*);
+static void client_connect_cback(tGATT_IF, const RawAddress&, tCONN_ID, bool, tGATT_DISCONN_REASON,
+ tBT_TRANSPORT);
+static void client_cmpl_cback(tCONN_ID, tGATTC_OPTYPE, tGATT_STATUS, tGATT_CL_COMPLETE*);
tGATT_CBACK gap_cback = {
.p_conn_cb = client_connect_cback,
@@ -88,7 +86,7 @@
tGATT_IF gatt_if;
/** returns LCB with matching bd address, or nullptr */
-tGAP_CLCB* find_clcb_by_bd_addr(const RawAddress& bda) {
+static tGAP_CLCB* find_clcb_by_bd_addr(const RawAddress& bda) {
for (auto& cb : gap_clcbs) {
if (cb.bda == bda) {
return &cb;
@@ -99,7 +97,7 @@
}
/** returns LCB with matching connection ID, or nullptr if not found */
-tGAP_CLCB* ble_find_clcb_by_conn_id(tCONN_ID conn_id) {
+static tGAP_CLCB* ble_find_clcb_by_conn_id(tCONN_ID conn_id) {
for (auto& cb : gap_clcbs) {
if (cb.connected && cb.conn_id == conn_id) {
return &cb;
@@ -110,7 +108,7 @@
}
/** allocates a GAP connection link control block */
-tGAP_CLCB* clcb_alloc(const RawAddress& bda) {
+static tGAP_CLCB* clcb_alloc(const RawAddress& bda) {
gap_clcbs.emplace_back();
tGAP_CLCB& cb = gap_clcbs.back();
cb.bda = bda;
@@ -118,7 +116,7 @@
}
/** The function clean up the pending request queue in GAP */
-void clcb_dealloc(tGAP_CLCB& clcb) {
+static void clcb_dealloc(tGAP_CLCB& clcb) {
// put last element into place of current element, and remove last one - just
// fast remove.
for (auto it = gap_clcbs.begin(); it != gap_clcbs.end(); it++) {
@@ -132,7 +130,7 @@
}
/** GAP Attributes Database Request callback */
-tGATT_STATUS read_attr_value(uint16_t handle, tGATT_VALUE* p_value, bool is_long) {
+static tGATT_STATUS read_attr_value(uint16_t handle, tGATT_VALUE* p_value, bool is_long) {
uint8_t* p = p_value->value;
uint16_t offset = p_value->offset;
uint8_t* p_dev_name = NULL;
@@ -191,7 +189,7 @@
}
/** GAP Attributes Database Read/Read Blob Request process */
-tGATT_STATUS proc_read(tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, tGATTS_RSP* p_rsp) {
+static tGATT_STATUS proc_read(tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data, tGATTS_RSP* p_rsp) {
if (p_data->is_long) {
p_rsp->attr_value.offset = p_data->offset;
}
@@ -202,7 +200,7 @@
}
/** GAP ATT server process a write request */
-tGATT_STATUS proc_write_req(tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) {
+static tGATT_STATUS proc_write_req(tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) {
for (const auto& db_addr : gatt_attr) {
if (p_data->handle == db_addr.handle) {
return GATT_WRITE_NOT_PERMIT;
@@ -213,8 +211,8 @@
}
/** GAP ATT server attribute access request callback */
-void server_attr_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type,
- tGATTS_DATA* p_data) {
+static void server_attr_request_cback(tCONN_ID conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type,
+ tGATTS_DATA* p_data) {
tGATT_STATUS status = GATT_INVALID_PDU;
bool ignore = false;
@@ -262,7 +260,7 @@
* Utility function to send a read request for GAP characteristics.
* Returns true if read started, else false if GAP is busy.
*/
-bool send_cl_read_request(tGAP_CLCB& clcb) {
+static bool send_cl_read_request(tGAP_CLCB& clcb) {
if (!clcb.requests.size() || clcb.cl_op_uuid != 0) {
return false;
}
@@ -288,7 +286,7 @@
}
/** GAP client operation complete callback */
-void cl_op_cmpl(tGAP_CLCB& clcb, bool status, uint16_t len, uint8_t* p_name) {
+static void cl_op_cmpl(tGAP_CLCB& clcb, bool status, uint16_t len, uint8_t* p_name) {
tGAP_BLE_CMPL_CBACK* p_cback = clcb.p_cback;
uint16_t op = clcb.cl_op_uuid;
@@ -311,8 +309,8 @@
}
/** Client connection callback */
-void client_connect_cback(tGATT_IF, const RawAddress& bda, tCONN_ID conn_id, bool connected,
- tGATT_DISCONN_REASON /* reason */, tBT_TRANSPORT) {
+static void client_connect_cback(tGATT_IF, const RawAddress& bda, tCONN_ID conn_id, bool connected,
+ tGATT_DISCONN_REASON /* reason */, tBT_TRANSPORT) {
tGAP_CLCB* p_clcb = find_clcb_by_bd_addr(bda);
if (p_clcb == NULL) {
log::info("No active GAP service found for peer:{} callback:{}", bda,
@@ -336,8 +334,8 @@
}
/** Client operation complete callback */
-void client_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
- tGATT_CL_COMPLETE* p_data) {
+static void client_cmpl_cback(tCONN_ID conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+ tGATT_CL_COMPLETE* p_data) {
tGAP_CLCB* p_clcb = ble_find_clcb_by_conn_id(conn_id);
uint16_t op_type;
uint16_t min, max, latency, tout;
@@ -396,8 +394,8 @@
}
}
-bool accept_client_operation(const RawAddress& peer_bda, uint16_t uuid,
- tGAP_BLE_CMPL_CBACK* p_cback) {
+static bool accept_client_operation(const RawAddress& peer_bda, uint16_t uuid,
+ tGAP_BLE_CMPL_CBACK* p_cback) {
if (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM) {
return false;
}
diff --git a/system/stack/gap/gap_conn.cc b/system/stack/gap/gap_conn.cc
index 8208edf..fd988c8 100644
--- a/system/stack/gap/gap_conn.cc
+++ b/system/stack/gap/gap_conn.cc
@@ -21,6 +21,7 @@
#include <string.h>
#include "gap_api.h"
+#include "gap_int.h"
#include "hci/controller_interface.h"
#include "internal_include/bt_target.h"
#include "main/shim/entry.h"
@@ -34,9 +35,6 @@
#include "types/bt_transport.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
/* Define the GAP Connection Control Block */
@@ -117,7 +115,7 @@
* Returns void
*
******************************************************************************/
-void gap_conn_init(void) {
+static void gap_conn_init(void) {
memset(&conn, 0, sizeof(tGAP_CONN));
conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
@@ -1050,8 +1048,6 @@
}
}
-void gap_attr_db_init(void);
-
/*
* This routine should not be called except once per stack invocation.
*/
diff --git a/system/stack/gap/gap_int.h b/system/stack/gap/gap_int.h
new file mode 100644
index 0000000..c63a4ce
--- /dev/null
+++ b/system/stack/gap/gap_int.h
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/// GAP ATT database initialization.
+void gap_attr_db_init(void);
diff --git a/system/stack/gatt/att_protocol.cc b/system/stack/gatt/att_protocol.cc
index 60bf695..8360b81 100644
--- a/system/stack/gatt/att_protocol.cc
+++ b/system/stack/gatt/att_protocol.cc
@@ -37,10 +37,6 @@
#define GATT_OP_CODE_SIZE 1
#define GATT_START_END_HANDLE_SIZE 4
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
-using base::StringPrintf;
using bluetooth::Uuid;
using namespace bluetooth;
diff --git a/system/stack/gatt/gatt_api.cc b/system/stack/gatt/gatt_api.cc
index 7ed0fe0..3f2c713 100644
--- a/system/stack/gatt/gatt_api.cc
+++ b/system/stack/gatt/gatt_api.cc
@@ -51,9 +51,6 @@
#include "types/bt_transport.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth::legacy::stack::sdp;
using namespace bluetooth;
@@ -63,7 +60,7 @@
* Add a service handle range to the list in descending order of the start
* handle. Return reference to the newly added element.
**/
-tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) {
+static tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) {
auto lst_ptr = gatt_cb.hdl_list_info;
auto it = lst_ptr->begin();
for (; it != lst_ptr->end(); it++) {
@@ -353,7 +350,7 @@
return GATT_SERVICE_STARTED;
}
-bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) {
+static bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) {
for (auto& info : *gatt_cb.srv_list_info) {
Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db);
diff --git a/system/stack/gatt/gatt_attr.cc b/system/stack/gatt/gatt_attr.cc
index a4b2935..a9d9e12 100644
--- a/system/stack/gatt/gatt_attr.cc
+++ b/system/stack/gatt/gatt_attr.cc
@@ -40,10 +40,6 @@
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
-using base::StringPrintf;
using bluetooth::Uuid;
using namespace bluetooth;
@@ -192,8 +188,8 @@
* block.
*
******************************************************************************/
-tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(tCONN_ID conn_id, const RawAddress& bda,
- tBT_TRANSPORT tranport) {
+static tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(tCONN_ID conn_id, const RawAddress& bda,
+ tBT_TRANSPORT tranport) {
uint8_t i_clcb = 0;
tGATT_PROFILE_CLCB* p_clcb = NULL;
@@ -224,13 +220,13 @@
* Returns void
*
******************************************************************************/
-void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* p_clcb) {
+static void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* p_clcb) {
memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
}
/** GAP Attributes Database Request callback */
-tGATT_STATUS read_attr_value(tCONN_ID conn_id, uint16_t handle, tGATT_VALUE* p_value,
- bool is_long) {
+static tGATT_STATUS read_attr_value(tCONN_ID conn_id, uint16_t handle, tGATT_VALUE* p_value,
+ bool is_long) {
uint8_t* p = p_value->value;
if (handle == gatt_cb.handle_sr_supported_feat) {
@@ -271,8 +267,8 @@
}
/** GAP Attributes Database Read/Read Blob Request process */
-tGATT_STATUS proc_read_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data,
- tGATTS_RSP* p_rsp) {
+static tGATT_STATUS proc_read_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_READ_REQ* p_data,
+ tGATTS_RSP* p_rsp) {
if (p_data->is_long) {
p_rsp->attr_value.offset = p_data->offset;
}
@@ -283,7 +279,7 @@
}
/** GAP ATT server process a write request */
-tGATT_STATUS proc_write_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) {
+static tGATT_STATUS proc_write_req(tCONN_ID conn_id, tGATTS_REQ_TYPE, tGATT_WRITE_REQ* p_data) {
uint16_t handle = p_data->handle;
/* GATT_UUID_SERVER_SUP_FEAT*/
diff --git a/system/stack/gatt/gatt_auth.cc b/system/stack/gatt/gatt_auth.cc
index fc11e25..4323c8e 100644
--- a/system/stack/gatt/gatt_auth.cc
+++ b/system/stack/gatt/gatt_auth.cc
@@ -39,9 +39,6 @@
#include "stack/include/btm_status.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
/*******************************************************************************
@@ -281,7 +278,7 @@
* This routine determine the security action based on auth_request and current
* link status. Returns tGATT_SEC_ACTION (security action)
*/
-tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* p_clcb) {
+static tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* p_clcb) {
tGATT_SEC_ACTION act = GATT_SEC_OK;
tGATT_TCB* p_tcb = p_clcb->p_tcb;
tGATT_AUTH_REQ auth_req = p_clcb->auth_req;
diff --git a/system/stack/gatt/gatt_cl.cc b/system/stack/gatt/gatt_cl.cc
index 61fb47f..5084496 100644
--- a/system/stack/gatt/gatt_cl.cc
+++ b/system/stack/gatt/gatt_cl.cc
@@ -52,9 +52,6 @@
#define L2CAP_PKT_OVERHEAD 4
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
using bluetooth::Uuid;
using bluetooth::eatt::EattChannel;
@@ -277,6 +274,7 @@
return;
}
}
+
/*******************************************************************************
*
* Function gatt_send_queue_write_cancel
@@ -299,6 +297,7 @@
gatt_end_operation(p_clcb, rt, NULL);
}
}
+
/*******************************************************************************
*
* Function gatt_check_write_long_terminate
@@ -308,7 +307,8 @@
* Returns true: write long is terminated; false keep sending.
*
******************************************************************************/
-bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, tGATT_VALUE* p_rsp_value) {
+static bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
+ tGATT_VALUE* p_rsp_value) {
tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
bool terminate = false;
tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
@@ -389,8 +389,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_find_type_value_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_find_type_value_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint16_t len,
+ uint8_t* p_data) {
tGATT_DISC_RES result;
uint8_t* p = p_data;
@@ -434,8 +434,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_read_info_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t /* op_code */,
- uint16_t len, uint8_t* p_data) {
+static void gatt_process_read_info_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb,
+ uint8_t /* op_code */, uint16_t len, uint8_t* p_data) {
tGATT_DISC_RES result;
uint8_t *p = p_data, uuid_len = 0, type;
@@ -481,6 +481,7 @@
/* initiate another request */
gatt_act_discovery(p_clcb);
}
+
/*******************************************************************************
*
* Function gatt_proc_disc_error_rsp
@@ -491,8 +492,8 @@
* Returns void.
*
******************************************************************************/
-void gatt_proc_disc_error_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t opcode,
- uint16_t /* handle */, uint8_t reason) {
+static void gatt_proc_disc_error_rsp(tGATT_TCB& /* tcb */, tGATT_CLCB* p_clcb, uint8_t opcode,
+ uint16_t /* handle */, uint8_t reason) {
tGATT_STATUS status = (tGATT_STATUS)reason;
log::verbose("reason: {:02x} cmd_code {:04x}", reason, opcode);
@@ -525,8 +526,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_error_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */,
+ uint16_t len, uint8_t* p_data) {
uint8_t opcode, *p = p_data;
uint8_t reason;
uint16_t handle;
@@ -569,6 +570,7 @@
}
}
}
+
/*******************************************************************************
*
* Function gatt_process_prep_write_rsp
@@ -579,8 +581,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_prep_write_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code,
+ uint16_t len, uint8_t* p_data) {
uint8_t* p = p_data;
tGATT_VALUE value = {
@@ -630,8 +632,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_notification(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
+ uint8_t* p_data) {
tGATT_VALUE value = {};
tGATT_REG* p_reg;
tCONN_ID conn_id;
@@ -815,8 +817,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code,
- uint16_t len, uint8_t* p_data) {
+static void gatt_process_read_by_type_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t op_code,
+ uint16_t len, uint8_t* p_data) {
tGATT_DISC_RES result;
tGATT_DISC_VALUE record_value;
uint8_t *p = p_data, value_len, handle_len = 2;
@@ -1027,8 +1029,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_read_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint8_t /* op_code */,
+ uint16_t len, uint8_t* p_data) {
uint16_t offset = p_clcb->counter;
uint8_t* p = p_data;
@@ -1110,7 +1112,10 @@
* Returns void
*
******************************************************************************/
-void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) { gatt_end_operation(p_clcb, GATT_SUCCESS, NULL); }
+static void gatt_process_handle_rsp(tGATT_CLCB* p_clcb) {
+ gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+}
+
/*******************************************************************************
*
* Function gatt_process_mtu_rsp
@@ -1121,7 +1126,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len, uint8_t* p_data) {
+static void gatt_process_mtu_rsp(tGATT_TCB& tcb, tGATT_CLCB* p_clcb, uint16_t len,
+ uint8_t* p_data) {
uint16_t mtu;
tGATT_STATUS status = GATT_SUCCESS;
@@ -1173,7 +1179,7 @@
* Returns response code.
*
******************************************************************************/
-uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) {
+static uint8_t gatt_cmd_to_rsp_code(uint8_t cmd_code) {
uint8_t rsp_code = 0;
if (cmd_code > 1 && cmd_code != GATT_CMD_WRITE) {
diff --git a/system/stack/gatt/gatt_db.cc b/system/stack/gatt/gatt_db.cc
index 2141fd4..cd55ffd 100644
--- a/system/stack/gatt/gatt_db.cc
+++ b/system/stack/gatt/gatt_db.cc
@@ -31,9 +31,6 @@
#include "stack/include/l2cap_types.h"
#include "types/bluetooth/uuid.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using bluetooth::Uuid;
using namespace bluetooth;
@@ -442,7 +439,7 @@
/******************************************************************************/
/* Service Attribute Database Query Utility Functions */
/******************************************************************************/
-tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) {
+static tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) {
if (!p_db) {
return nullptr;
}
diff --git a/system/stack/gatt/gatt_int.h b/system/stack/gatt/gatt_int.h
index 59dc338..88c8b88 100644
--- a/system/stack/gatt/gatt_int.h
+++ b/system/stack/gatt/gatt_int.h
@@ -499,10 +499,6 @@
int8_t initiating_phys);
bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
tBT_TRANSPORT transport, int8_t initiating_phys);
-bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBT_TRANSPORT transport,
- uint8_t initiating_phys, tGATT_IF gatt_if);
-bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBLE_ADDR_TYPE addr_type,
- tBT_TRANSPORT transport, uint8_t initiating_phys, tGATT_IF gatt_if);
void gatt_data_process(tGATT_TCB& p_tcb, uint16_t cid, BT_HDR* p_buf);
void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb, bool is_add,
bool check_acl_link);
@@ -692,10 +688,20 @@
tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long, uint16_t handle,
tGATT_SEC_FLAG sec_flag, uint8_t key_size);
bluetooth::Uuid* gatts_get_service_uuid(tGATT_SVC_DB* p_db);
+void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb);
/* gatt_sr_hash.cc */
Octet16 gatts_calculate_database_hash(std::list<tGATT_SRV_LIST_ELEM>* lst_ptr);
+namespace bluetooth {
+namespace legacy {
+namespace testing {
+BT_HDR* attp_build_value_cmd(uint16_t payload_size, uint8_t op_code, uint16_t handle,
+ uint16_t offset, uint16_t len, uint8_t* p_data);
+} // namespace testing
+} // namespace legacy
+} // namespace bluetooth
+
namespace fmt {
template <>
struct formatter<tGATT_CH_STATE> : enum_formatter<tGATT_CH_STATE> {};
diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc
index f5591d2..2cf2c42 100644
--- a/system/stack/gatt/gatt_main.cc
+++ b/system/stack/gatt/gatt_main.cc
@@ -45,15 +45,13 @@
#include "stack/include/bt_psm_types.h"
#include "stack/include/bt_types.h"
#include "stack/include/btm_client_interface.h"
+#include "stack/include/gatt_api.h"
#include "stack/include/l2cap_acl_interface.h"
#include "stack/include/l2cap_interface.h"
#include "stack/include/l2cdefs.h"
#include "stack/include/srvc_api.h" // tDIS_VALUE
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using bluetooth::eatt::EattExtension;
using namespace bluetooth;
@@ -218,8 +216,8 @@
* Returns true if connection is started, otherwise return false.
*
******************************************************************************/
-bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tGATT_TCB* p_tcb,
- tBT_TRANSPORT transport, uint8_t /* initiating_phys */, tGATT_IF gatt_if) {
+static bool gatt_connect(const RawAddress& rem_bda, tBLE_ADDR_TYPE addr_type, tGATT_TCB* p_tcb,
+ tBT_TRANSPORT transport, uint8_t /* initiating_phys */, tGATT_IF gatt_if) {
if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN) {
gatt_set_ch_state(p_tcb, GATT_CH_CONN);
}
@@ -240,11 +238,6 @@
return connection_manager::create_le_connection(gatt_if, rem_bda, addr_type);
}
-bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb, tBT_TRANSPORT transport,
- uint8_t initiating_phys, tGATT_IF gatt_if) {
- return gatt_connect(rem_bda, BLE_ADDR_PUBLIC, p_tcb, transport, initiating_phys, gatt_if);
-}
-
/*******************************************************************************
*
* Function gatt_cancel_connect
diff --git a/system/stack/gatt/gatt_sr.cc b/system/stack/gatt/gatt_sr.cc
index 7e12f30..8b67f2e 100644
--- a/system/stack/gatt/gatt_sr.cc
+++ b/system/stack/gatt/gatt_sr.cc
@@ -44,9 +44,6 @@
#define GATT_MTU_REQ_MIN_LEN 2
#define L2CAP_PKT_OVERHEAD 4
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using bluetooth::Uuid;
using bluetooth::eatt::EattChannel;
using bluetooth::eatt::EattExtension;
@@ -107,7 +104,7 @@
* Returns true if empty, false if there is pending command.
*
******************************************************************************/
-bool gatt_sr_cmd_empty(tGATT_TCB& tcb, uint16_t cid) {
+static bool gatt_sr_cmd_empty(tGATT_TCB& tcb, uint16_t cid) {
if (cid == tcb.att_lcid) {
return tcb.sr_cmd.op_code == 0;
}
@@ -369,8 +366,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_exec_write_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
+ uint8_t* p_data) {
uint8_t *p = p_data, flag;
uint32_t trans_id = 0;
tGATT_IF gatt_if;
@@ -441,8 +438,8 @@
* Returns void
*
******************************************************************************/
-void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
- uint8_t* p_data) {
+static void gatt_process_read_multi_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
+ uint8_t* p_data) {
uint32_t trans_id;
uint16_t handle = 0, ll = len;
uint8_t* p = p_data;
@@ -730,8 +727,8 @@
* Returns void
*
******************************************************************************/
-void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
- uint8_t* p_data) {
+static void gatts_process_primary_service_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code,
+ uint16_t len, uint8_t* p_data) {
uint16_t s_hdl = 0, e_hdl = 0;
Uuid uuid = Uuid::kEmpty;
@@ -1144,8 +1141,8 @@
* Returns void
*
******************************************************************************/
-void gatts_process_attribute_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
- uint8_t* p_data) {
+static void gatts_process_attribute_req(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code, uint16_t len,
+ uint8_t* p_data) {
uint16_t handle = 0;
uint8_t* p = p_data;
tGATT_STATUS status = GATT_INVALID_HANDLE;
@@ -1291,7 +1288,7 @@
* Returns void
*
******************************************************************************/
-void gatts_process_value_conf(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code) {
+static void gatts_process_value_conf(tGATT_TCB& tcb, uint16_t cid, uint8_t op_code) {
uint16_t handle;
if (!gatt_tcb_find_indicate_handle(tcb, cid, &handle)) {
diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc
index d159bbd..5be17c3 100644
--- a/system/stack/gatt/gatt_utils.cc
+++ b/system/stack/gatt/gatt_utils.cc
@@ -45,16 +45,12 @@
#include "stack/include/bt_psm_types.h"
#include "stack/include/bt_types.h"
#include "stack/include/bt_uuid16.h"
+#include "stack/include/btm_sec_api.h"
#include "stack/include/l2cdefs.h"
#include "stack/include/sdp_api.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
-uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr);
-
using namespace bluetooth::legacy::stack::sdp;
using namespace bluetooth;
@@ -108,7 +104,7 @@
return ATT_MTU_DEFAULT;
}
-uint16_t gatt_get_max_phy_channel() {
+static uint16_t gatt_get_max_phy_channel() {
static const uint16_t MAX_PHY_CHANNEL =
std::min(std::max(osi_property_get_int32(
"bluetooth.core.le.max_number_of_concurrent_connections", 0),
@@ -126,7 +122,7 @@
* Returns None
*
******************************************************************************/
-void gatt_free_pending_ind(tGATT_TCB* p_tcb) {
+static void gatt_free_pending_ind(tGATT_TCB* p_tcb) {
log::verbose("");
if (p_tcb->pending_ind_q == NULL) {
@@ -377,28 +373,6 @@
/*******************************************************************************
*
- * Function gatt_is_bda_connected
- *
- * Description
- *
- * Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
- *
- ******************************************************************************/
-bool gatt_is_bda_connected(const RawAddress& bda) {
- uint8_t i = 0;
- bool connected = false;
-
- for (i = 0; i < gatt_get_max_phy_channel(); i++) {
- if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].peer_bda == bda) {
- connected = true;
- break;
- }
- }
- return connected;
-}
-
-/*******************************************************************************
- *
* Function gatt_find_i_tcb_by_addr
*
* Description Search for an empty tcb entry, and return the index.
@@ -406,7 +380,7 @@
* Returns GATT_INDEX_INVALID if not found. Otherwise index to the tcb.
*
******************************************************************************/
-uint8_t gatt_find_i_tcb_by_addr(const RawAddress& bda, tBT_TRANSPORT transport) {
+static uint8_t gatt_find_i_tcb_by_addr(const RawAddress& bda, tBT_TRANSPORT transport) {
uint8_t i = 0;
for (; i < gatt_get_max_phy_channel(); i++) {
@@ -794,8 +768,6 @@
}
}
-void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb);
-
/*******************************************************************************
*
* Function gatt_indication_confirmation_timeout
diff --git a/system/stack/include/acl_hci_link_interface.h b/system/stack/include/acl_hci_link_interface.h
index 561d56a..ac17f0d 100644
--- a/system/stack/include/acl_hci_link_interface.h
+++ b/system/stack/include/acl_hci_link_interface.h
@@ -58,6 +58,7 @@
void acl_process_supported_features(uint16_t handle, uint64_t features);
void acl_process_extended_features(uint16_t handle, uint8_t current_page_number,
uint8_t max_page_number, uint64_t features);
+void btm_pm_reset();
void btm_pm_on_mode_change(tHCI_STATUS status, uint16_t handle, tHCI_MODE current_mode,
uint16_t interval);
void btm_pm_on_sniff_subrating(tHCI_STATUS status, uint16_t handle,
diff --git a/system/stack/include/gatt_api.h b/system/stack/include/gatt_api.h
index e51ddc0..54ecfdc 100644
--- a/system/stack/include/gatt_api.h
+++ b/system/stack/include/gatt_api.h
@@ -1272,6 +1272,10 @@
// Frees resources used by the GATT profile.
void gatt_free(void);
+void gatt_consolidate(const RawAddress& identity_addr, const RawAddress& rpa);
+void gatt_notify_conn_update(const RawAddress& remote, uint16_t interval, uint16_t latency,
+ uint16_t timeout, tHCI_STATUS status);
+
// Link encryption complete notification for all encryption process
// initiated outside GATT.
void gatt_notify_enc_cmpl(const RawAddress& bd_addr);
@@ -1283,6 +1287,8 @@
// Initialize GATTS list of bonded device service change updates.
void gatt_load_bonded(void);
+void gatt_tcb_dump(int fd);
+
namespace fmt {
template <>
struct formatter<GattStatus> : enum_formatter<GattStatus> {};
diff --git a/system/stack/include/smp_api.h b/system/stack/include/smp_api.h
index b9eeee4..6957c71 100644
--- a/system/stack/include/smp_api.h
+++ b/system/stack/include/smp_api.h
@@ -207,4 +207,6 @@
// Proceed to send LTK, DIV and ER to central if bonding the devices.
void smp_link_encrypted(const RawAddress& bda, uint8_t encr_enable);
+void smp_cancel_start_encryption_attempt();
+
#endif /* SMP_API_H */
diff --git a/system/stack/l2cap/internal/l2c_api.h b/system/stack/l2cap/internal/l2c_api.h
index 6f65f81..5ed3403 100644
--- a/system/stack/l2cap/internal/l2c_api.h
+++ b/system/stack/l2cap/internal/l2c_api.h
@@ -75,7 +75,7 @@
#define L2CAP_FCR_CHAN_OPT_ALL_MASK (L2CAP_FCR_CHAN_OPT_BASIC | L2CAP_FCR_CHAN_OPT_ERTM)
/* Validity check for PSM. PSM values must be odd. Also, all PSM values must
- * be assigned such that the least significant bit of the most sigificant
+ * be assigned such that the least significant bit of the most significant
* octet equals zero.
*/
#define L2C_INVALID_PSM(psm) (((psm) & 0x0101) != 0x0001)
diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc
index a233046..b958745 100644
--- a/system/stack/l2cap/l2c_api.cc
+++ b/system/stack/l2cap/l2c_api.cc
@@ -24,7 +24,7 @@
#define LOG_TAG "bt_l2cap"
-#include "stack/l2cap/internal/l2c_api.h"
+#include "stack/l2cap/l2c_api.h"
#include <base/location.h>
#include <base/strings/stringprintf.h>
@@ -47,6 +47,7 @@
#include "stack/include/btm_client_interface.h"
#include "stack/include/l2cap_module.h"
#include "stack/include/main_thread.h"
+#include "stack/l2cap/internal/l2c_api.h"
#include "stack/l2cap/l2c_int.h"
#include "types/raw_address.h"
@@ -1639,7 +1640,7 @@
return;
}
- if (snoop_logger->GetBtSnoopMode() != snoop_logger->kBtSnoopLogModeFiltered) {
+ if (snoop_logger->GetCurrentSnoopMode() != snoop_logger->kBtSnoopLogModeFiltered) {
return;
}
diff --git a/system/stack/smp/smp_act.cc b/system/stack/smp/smp_act.cc
index 07502a2..6de1db3 100644
--- a/system/stack/smp/smp_act.cc
+++ b/system/stack/smp/smp_act.cc
@@ -39,12 +39,10 @@
#include "stack/include/btm_client_interface.h"
#include "stack/include/btm_log_history.h"
#include "stack/include/btm_status.h"
+#include "stack/include/smp_api.h"
#include "stack/include/smp_api_types.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
namespace {
diff --git a/system/stack/smp/smp_int.h b/system/stack/smp/smp_int.h
index 29782128..dd51c0d 100644
--- a/system/stack/smp/smp_int.h
+++ b/system/stack/smp/smp_int.h
@@ -489,6 +489,10 @@
bool smp_calculate_link_key_from_long_term_key(tSMP_CB* p_cb);
bool smp_calculate_long_term_key_from_link_key(tSMP_CB* p_cb);
+Octet16 smp_gen_p1_4_confirm(tSMP_CB* p_cb, tBLE_ADDR_TYPE remote_bd_addr_type);
+Octet16 smp_gen_p2_4_confirm(tSMP_CB* p_cb, const RawAddress& remote_bda);
+tSMP_STATUS smp_calculate_confirm(tSMP_CB* p_cb, const Octet16& rand, Octet16* output);
+
void print128(const Octet16& x, const char* key_name);
void smp_xor_128(Octet16* a, const Octet16& b);
diff --git a/system/stack/smp/smp_keys.cc b/system/stack/smp/smp_keys.cc
index 801a3d4..f0fb8b9 100644
--- a/system/stack/smp/smp_keys.cc
+++ b/system/stack/smp/smp_keys.cc
@@ -47,9 +47,6 @@
#include "stack/include/main_thread.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using bluetooth::common::BindOnce;
using bluetooth::common::OnceCallback;
using crypto_toolbox::aes_128;
@@ -84,19 +81,16 @@
bool smp_has_local_oob_data() { return !is_oob_data_empty(&saved_local_oob_data); }
-void smp_debug_print_nbyte_little_endian(uint8_t* /* p */, const char* /* key_name */,
- uint8_t /* len */) {}
+static void smp_debug_print_nbyte_little_endian(uint8_t* /* p */, const char* /* key_name */,
+ uint8_t /* len */) {}
-inline void smp_debug_print_nbyte_little_endian(const Octet16& p, const char* key_name,
+static void smp_debug_print_nbyte_little_endian(const Octet16& p, const char* key_name,
uint8_t len) {
smp_debug_print_nbyte_little_endian(const_cast<uint8_t*>(p.data()), key_name, len);
}
-void smp_debug_print_nbyte_big_endian(uint8_t* /* p */, const char* /* key_name */,
- uint8_t /* len */) {}
-
/** This function is called to process a passkey. */
-void smp_proc_passkey(tSMP_CB* p_cb, uint64_t rand) {
+static void smp_proc_passkey(tSMP_CB* p_cb, uint64_t rand) {
uint8_t* tt = p_cb->tk.data();
uint32_t passkey = static_cast<uint32_t>(rand & SMP_PASSKEY_MASK);
@@ -176,7 +170,7 @@
/**
* This function is called to calculate CSRK
*/
-void smp_compute_csrk(uint16_t div, tSMP_CB* p_cb) {
+static void smp_compute_csrk(uint16_t div, tSMP_CB* p_cb) {
Octet16 buffer{}; /* for (r || DIV) r=1*/
uint16_t r = 1;
uint8_t* p = buffer.data();
@@ -216,10 +210,10 @@
}
/*******************************************************************************
- * Function smp_concatenate_peer - LSB first
+ * Function smp_concatenate_local - LSB first
* add pairing command sent from local device into p1.
******************************************************************************/
-void smp_concatenate_local(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) {
+static void smp_concatenate_local(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) {
uint8_t* p = *p_data;
log::verbose("addr:{}", p_cb->pairing_bda);
@@ -238,7 +232,7 @@
* Function smp_concatenate_peer - LSB first
* add pairing command received from peer device into p1.
******************************************************************************/
-void smp_concatenate_peer(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) {
+static void smp_concatenate_peer(tSMP_CB* p_cb, uint8_t** p_data, uint8_t op_code) {
uint8_t* p = *p_data;
log::verbose("addr:{}", p_cb->pairing_bda);
diff --git a/system/stack/smp/smp_l2c.cc b/system/stack/smp/smp_l2c.cc
index 04b6249..219cb72 100644
--- a/system/stack/smp/smp_l2c.cc
+++ b/system/stack/smp/smp_l2c.cc
@@ -263,7 +263,19 @@
log::info("BDA:{} pairing_bda:{}, connected:{}", bd_addr, p_cb->pairing_bda, connected);
if (bd_addr != p_cb->pairing_bda) {
- return;
+ if (!com::android::bluetooth::flags::smp_state_machine_stuck_after_disconnection_fix()) {
+ log::info(
+ "If your pairing failed, get a build with "
+ "smp_state_machine_stuck_after_disconnection_fix and try again :)");
+ return;
+ }
+
+ tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
+ /* When pairing was initiated to RPA, and connection was on LE transport first using RPA, then
+ * we must check record pseudo address, it might be same device */
+ if (p_dev_rec == nullptr || p_dev_rec->RemoteAddress() != p_cb->pairing_bda) {
+ return;
+ }
}
/* Check if we already finished SMP pairing over LE, and are waiting to
diff --git a/system/stack/smp/smp_utils.cc b/system/stack/smp/smp_utils.cc
index 01a045b..bcde927 100644
--- a/system/stack/smp/smp_utils.cc
+++ b/system/stack/smp/smp_utils.cc
@@ -71,9 +71,6 @@
Check*/)
#define SMP_PAIR_KEYPR_NOTIF_SIZE (1 /* opcode */ + 1 /*Notif Type*/)
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
namespace {
@@ -341,7 +338,7 @@
* Description Send message to L2CAP.
*
******************************************************************************/
-bool smp_send_msg_to_L2CAP(const RawAddress& rem_bda, BT_HDR* p_toL2CAP) {
+static bool smp_send_msg_to_L2CAP(const RawAddress& rem_bda, BT_HDR* p_toL2CAP) {
tL2CAP_DW_RESULT l2cap_ret;
uint16_t fixed_cid = L2CAP_SMP_CID;
diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc
index c1b90ee..c308911 100644
--- a/system/stack/test/btm/stack_btm_test.cc
+++ b/system/stack/test/btm/stack_btm_test.cc
@@ -277,25 +277,4 @@
.c_str());
}
-bool is_disconnect_reason_valid(const tHCI_REASON& reason);
-TEST_F(StackBtmWithInitFreeTest, is_disconnect_reason_valid) {
- std::set<tHCI_REASON> valid_reason_set{
- HCI_ERR_AUTH_FAILURE,
- HCI_ERR_PEER_USER,
- HCI_ERR_REMOTE_LOW_RESOURCE,
- HCI_ERR_REMOTE_POWER_OFF,
- HCI_ERR_UNSUPPORTED_REM_FEATURE,
- HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED,
- HCI_ERR_UNACCEPT_CONN_INTERVAL,
- };
- for (unsigned u = 0; u < 256; u++) {
- const tHCI_REASON reason = static_cast<tHCI_REASON>(u);
- if (valid_reason_set.count(reason)) {
- ASSERT_TRUE(is_disconnect_reason_valid(reason));
- } else {
- ASSERT_FALSE(is_disconnect_reason_valid(reason));
- }
- }
-}
-
TEST_F(StackBtmWithInitFreeTest, Init) { ASSERT_FALSE(btm_cb.rnr.remname_active); }
diff --git a/system/stack/test/gatt/gatt_sr_test.cc b/system/stack/test/gatt/gatt_sr_test.cc
index 7992f87..285aa23 100644
--- a/system/stack/test/gatt/gatt_sr_test.cc
+++ b/system/stack/test/gatt/gatt_sr_test.cc
@@ -20,6 +20,7 @@
#include <cstdint>
#include <memory>
+#include "stack/connection_manager/connection_manager.h"
#include "stack/gatt/gatt_int.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/main_thread.h"
@@ -120,12 +121,8 @@
void gatt_update_app_use_link_flag(tGATT_IF /*gatt_if*/, tGATT_TCB* /*p_tcb*/, bool /*is_add*/,
bool /*check_acl_link*/) {}
bluetooth::common::MessageLoopThread* get_main_thread() { return nullptr; }
-void l2cble_set_fixed_channel_tx_data_length(const RawAddress& /*remote_bda*/, uint16_t /*fix_cid*/,
- uint16_t /*tx_mtu*/) {}
-void L2CA_SetLeFixedChannelTxDataLength(const RawAddress& /*remote_bda*/, uint16_t /*fix_cid*/,
- uint16_t /*tx_mtu*/) {}
-void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type,
- tGATTS_DATA* p_data) {
+static void ApplicationRequestCallback(uint16_t conn_id, uint32_t trans_id, tGATTS_REQ_TYPE type,
+ tGATTS_DATA* p_data) {
test_state_.application_request_callback.conn_id_ = conn_id;
test_state_.application_request_callback.trans_id_ = trans_id;
test_state_.application_request_callback.type_ = type;
diff --git a/system/stack/test/gatt/mock_gatt_utils_ref.cc b/system/stack/test/gatt/mock_gatt_utils_ref.cc
index 2f392b3..fcd7586 100644
--- a/system/stack/test/gatt/mock_gatt_utils_ref.cc
+++ b/system/stack/test/gatt/mock_gatt_utils_ref.cc
@@ -63,9 +63,3 @@
return 0x0000;
}
void gatt_dequeue_sr_cmd(tGATT_TCB& tcb, uint16_t cid) {}
-
-/** stack/l2cap/l2c_ble.cc */
-void l2cble_set_fixed_channel_tx_data_length(const RawAddress& remote_bda, uint16_t fix_cid,
- uint16_t tx_mtu) {}
-void L2CA_SetLeFixedChannelTxDataLength(const RawAddress& remote_bda, uint16_t fix_cid,
- uint16_t tx_mtu) {}
diff --git a/system/stack/test/stack_avctp_test.cc b/system/stack/test/stack_avctp_test.cc
index 17abac1..e617b64 100644
--- a/system/stack/test/stack_avctp_test.cc
+++ b/system/stack/test/stack_avctp_test.cc
@@ -30,14 +30,27 @@
namespace {
constexpr uint16_t kRemoteCid = 0x0123;
+constexpr uint16_t kRemoteBrowseCid = 0x0456;
const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
} // namespace
-class StackAvctpTest : public ::testing::Test {
+class StackAvctpWithMocksTest : public ::testing::Test {
protected:
void SetUp() override {
fake_osi_ = std::make_unique<::test::fake::FakeOsi>();
bluetooth::testing::stack::l2cap::set_interface(&mock_stack_l2cap_interface_);
+ }
+
+ void TearDown() override {}
+
+ bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
+ std::unique_ptr<test::fake::FakeOsi> fake_osi_;
+};
+
+class StackAvctpTest : public StackAvctpWithMocksTest {
+protected:
+ void SetUp() override {
+ StackAvctpWithMocksTest::SetUp();
EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _))
.WillRepeatedly([this](unsigned short psm, const tL2CAP_APPL_INFO& cb, bool /* c */,
tL2CAP_ERTM_INFO* /*d*/, unsigned short /* e */,
@@ -57,11 +70,10 @@
EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP));
EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE));
AVCT_Deregister();
+ StackAvctpWithMocksTest::TearDown();
}
std::map<uint16_t, tL2CAP_APPL_INFO> callback_map_;
- bluetooth::testing::stack::l2cap::Mock mock_stack_l2cap_interface_;
- std::unique_ptr<test::fake::FakeOsi> fake_osi_;
int fd_{STDOUT_FILENO};
};
@@ -126,3 +138,57 @@
AVCT_Dumpsys(fd_);
}
+
+TEST_F(StackAvctpWithMocksTest, AVCT_Lifecycle) {
+ // Register the AVCT profile and capture the l2cap callbacks
+ std::map<uint16_t, tL2CAP_APPL_INFO> callback_map;
+ EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_RegisterWithSecurity(_, _, _, _, _, _, _))
+ .WillRepeatedly([&callback_map](unsigned short psm, const tL2CAP_APPL_INFO& cb,
+ bool /* c */, tL2CAP_ERTM_INFO* /*d*/,
+ unsigned short /* e */, unsigned short /* f */,
+ unsigned short /* g */) {
+ callback_map.insert(std::make_tuple(psm, cb));
+ return psm;
+ });
+ AVCT_Register();
+
+ // Return well known l2cap channel IDs for each of the two PSMs
+ EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_ConnectReqWithSecurity(_, _, _))
+ .WillRepeatedly(
+ [](unsigned short psm, const RawAddress /* bd_addr */, uint16_t /* sec_level */) {
+ return (psm == BT_PSM_AVCTP) ? kRemoteCid : kRemoteBrowseCid;
+ });
+
+ uint8_t handle;
+ tAVCT_CC cc = {
+ .p_ctrl_cback = [](uint8_t /* handle */, uint8_t /* event */, uint16_t /* result */,
+ const RawAddress* /* peer_addr */) {},
+ .p_msg_cback = [](uint8_t /* handle */, uint8_t /* label */, uint8_t /* cr */,
+ BT_HDR* /* p_pkt */) {},
+ .pid = 0x1234,
+ .role = AVCT_ROLE_INITIATOR,
+ .control = 1,
+ };
+
+ // Initiate the creation of both control and browse AVCT connections
+ ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateConn(&handle, &cc, kRawAddress));
+ ASSERT_EQ(AVCT_SUCCESS, AVCT_CreateBrowse(handle, AVCT_ROLE_INITIATOR));
+
+ // Provide appropriate l2cap remote responses to open both channels
+ tL2CAP_CFG_INFO l2cap_cfg{};
+ callback_map[BT_PSM_AVCTP].pL2CA_ConnectCfm_Cb(kRemoteCid, tL2CAP_CONN::L2CAP_CONN_OK);
+ callback_map[BT_PSM_AVCTP].pL2CA_ConfigCfm_Cb(kRemoteCid, 0, &l2cap_cfg);
+ callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConnectCfm_Cb(kRemoteBrowseCid,
+ tL2CAP_CONN::L2CAP_CONN_OK);
+ callback_map[BT_PSM_AVCTP_BROWSE].pL2CA_ConfigCfm_Cb(kRemoteBrowseCid, 0, &l2cap_cfg);
+
+ // Close the profile by deregistering from l2cap
+ EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP));
+ EXPECT_CALL(mock_stack_l2cap_interface_, L2CA_Deregister(BT_PSM_AVCTP_BROWSE));
+ AVCT_Deregister();
+
+ // Ensure that API calls with a cached handle value or any run from a reactor
+ // thread or message loop do not fail
+ ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveBrowse(handle));
+ ASSERT_EQ(AVCT_SUCCESS, AVCT_RemoveConn(handle));
+}
diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp
index 846f9ec..af86f9f 100644
--- a/system/test/headless/Android.bp
+++ b/system/test/headless/Android.bp
@@ -71,6 +71,7 @@
"packages/modules/Bluetooth/system/stack/include",
],
static_libs: [
+ "aics",
"android.hardware.audio.common@5.0",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
@@ -119,9 +120,13 @@
"libudrv-uipc",
"libz",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libPlatformProperties",
"libaconfig_storage_read_api_cc",
+ "libbinder",
"libcrypto",
"libcutils", // property_get_bool
"libhidlbase",
diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc
index 8fb6163..5937d42 100644
--- a/system/test/mock/mock_bluetooth_interface.cc
+++ b/system/test/mock/mock_bluetooth_interface.cc
@@ -15,6 +15,7 @@
*/
#include <cstdint>
+#include <future>
#include "btif/include/stack_manager_t.h"
#include "hardware/bluetooth.h"
@@ -72,7 +73,7 @@
static void clean_up_stack(ProfileStopCallback /* stopProfiles */) {}
-static void start_up_rust_module_async() {}
+static void start_up_rust_module_async(std::promise<void> /* promise */) {}
static void shut_down_rust_module_async() {}
diff --git a/system/test/mock/mock_stack_acl.cc b/system/test/mock/mock_stack_acl.cc
index 1e85c50..d4504ba 100644
--- a/system/test/mock/mock_stack_acl.cc
+++ b/system/test/mock/mock_stack_acl.cc
@@ -27,17 +27,19 @@
#include <string>
#include "hci/class_of_device.h"
+#include "stack/include/acl_api.h"
#include "stack/include/acl_client_callbacks.h"
+#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/bt_hdr.h"
+#include "stack/include/btm_ble_api.h"
+#include "stack/include/inq_hci_link_interface.h"
+#include "stack/include/l2cap_acl_interface.h"
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
// Mocked compile conditionals, if any
// Mocked internal structures, if any
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
namespace test {
namespace mock {
namespace stack_acl {
@@ -63,9 +65,7 @@
acl_peer_supports_ble_connection_subrating_host;
struct acl_refresh_remote_address acl_refresh_remote_address;
struct acl_set_peer_le_features_from_handle acl_set_peer_le_features_from_handle;
-struct acl_get_connection_from_address acl_get_connection_from_address;
struct btm_acl_for_bda btm_acl_for_bda;
-struct acl_get_connection_from_handle acl_get_connection_from_handle;
struct BTM_ReadFailedContactCounter BTM_ReadFailedContactCounter;
struct BTM_ReadTxPower BTM_ReadTxPower;
struct BTM_SetLinkSuperTout BTM_SetLinkSuperTout;
@@ -98,28 +98,18 @@
struct btm_acl_process_sca_cmpl_pkt btm_acl_process_sca_cmpl_pkt;
struct btm_acl_removed btm_acl_removed;
struct btm_acl_role_changed btm_acl_role_changed;
-struct btm_acl_update_conn_addr btm_acl_update_conn_addr;
-struct btm_ble_refresh_local_resolvable_private_addr btm_ble_refresh_local_resolvable_private_addr;
struct btm_cont_rswitch_from_handle btm_cont_rswitch_from_handle;
struct btm_establish_continue_from_address btm_establish_continue_from_address;
-struct btm_process_remote_ext_features btm_process_remote_ext_features;
-struct btm_process_remote_version_complete btm_process_remote_version_complete;
struct btm_read_automatic_flush_timeout_complete btm_read_automatic_flush_timeout_complete;
struct btm_read_failed_contact_counter_complete btm_read_failed_contact_counter_complete;
-struct btm_read_failed_contact_counter_timeout btm_read_failed_contact_counter_timeout;
-struct btm_read_remote_ext_features btm_read_remote_ext_features;
struct btm_read_remote_ext_features_complete btm_read_remote_ext_features_complete;
struct btm_read_remote_ext_features_complete_raw btm_read_remote_ext_features_complete_raw;
struct btm_read_remote_ext_features_failed btm_read_remote_ext_features_failed;
struct btm_read_remote_version_complete btm_read_remote_version_complete;
struct btm_read_rssi_complete btm_read_rssi_complete;
-struct btm_read_rssi_timeout btm_read_rssi_timeout;
struct btm_read_tx_power_complete btm_read_tx_power_complete;
-struct btm_read_tx_power_timeout btm_read_tx_power_timeout;
struct btm_rejectlist_role_change_device btm_rejectlist_role_change_device;
-struct btm_set_link_policy btm_set_link_policy;
struct btm_set_packet_types_from_address btm_set_packet_types_from_address;
-struct hci_btm_set_link_supervision_timeout hci_btm_set_link_supervision_timeout;
struct on_acl_br_edr_connected on_acl_br_edr_connected;
struct on_acl_br_edr_failed on_acl_br_edr_failed;
struct BTM_unblock_role_switch_and_sniff_mode_for BTM_unblock_role_switch_and_sniff_mode_for;
@@ -210,18 +200,10 @@
inc_func_call_count(__func__);
test::mock::stack_acl::acl_send_data_packet_br_edr(bd_addr, p_buf);
}
-tACL_CONN* acl_get_connection_from_address(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
- inc_func_call_count(__func__);
- return test::mock::stack_acl::acl_get_connection_from_address(bd_addr, transport);
-}
tACL_CONN* btm_acl_for_bda(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
inc_func_call_count(__func__);
return test::mock::stack_acl::btm_acl_for_bda(bd_addr, transport);
}
-tACL_CONN* acl_get_connection_from_handle(uint16_t handle) {
- inc_func_call_count(__func__);
- return test::mock::stack_acl::acl_get_connection_from_handle(handle);
-}
tBTM_STATUS BTM_ReadFailedContactCounter(const RawAddress& remote_bda, tBTM_CMPL_CB* p_cb) {
inc_func_call_count(__func__);
return test::mock::stack_acl::BTM_ReadFailedContactCounter(remote_bda, p_cb);
@@ -354,15 +336,6 @@
inc_func_call_count(__func__);
test::mock::stack_acl::btm_acl_role_changed(hci_status, bd_addr, new_role);
}
-void btm_acl_update_conn_addr(uint16_t handle, const RawAddress& address) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_acl_update_conn_addr(handle, address);
-}
-void btm_ble_refresh_local_resolvable_private_addr(const RawAddress& pseudo_addr,
- const RawAddress& local_rpa) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_ble_refresh_local_resolvable_private_addr(pseudo_addr, local_rpa);
-}
void btm_cont_rswitch_from_handle(uint16_t hci_handle) {
inc_func_call_count(__func__);
test::mock::stack_acl::btm_cont_rswitch_from_handle(hci_handle);
@@ -371,16 +344,6 @@
inc_func_call_count(__func__);
test::mock::stack_acl::btm_establish_continue_from_address(bda, transport);
}
-void btm_process_remote_ext_features(tACL_CONN* p_acl_cb, uint8_t max_page_number) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_process_remote_ext_features(p_acl_cb, max_page_number);
-}
-void btm_process_remote_version_complete(uint8_t status, uint16_t handle, uint8_t lmp_version,
- uint16_t manufacturer, uint16_t lmp_subversion) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_process_remote_version_complete(status, handle, lmp_version,
- manufacturer, lmp_subversion);
-}
void btm_read_automatic_flush_timeout_complete(uint8_t* p) {
inc_func_call_count(__func__);
test::mock::stack_acl::btm_read_automatic_flush_timeout_complete(p);
@@ -389,14 +352,6 @@
inc_func_call_count(__func__);
test::mock::stack_acl::btm_read_failed_contact_counter_complete(p);
}
-void btm_read_failed_contact_counter_timeout(void* data) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_read_failed_contact_counter_timeout(data);
-}
-void btm_read_remote_ext_features(uint16_t handle, uint8_t page_number) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_read_remote_ext_features(handle, page_number);
-}
void btm_read_remote_ext_features_complete(uint16_t handle, uint8_t page_num, uint8_t max_page,
uint8_t* features) {
inc_func_call_count(__func__);
@@ -421,34 +376,18 @@
inc_func_call_count(__func__);
test::mock::stack_acl::btm_read_rssi_complete(p, evt_len);
}
-void btm_read_rssi_timeout(void* data) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_read_rssi_timeout(data);
-}
void btm_read_tx_power_complete(uint8_t* p, uint16_t evt_len, bool is_ble) {
inc_func_call_count(__func__);
test::mock::stack_acl::btm_read_tx_power_complete(p, evt_len, is_ble);
}
-void btm_read_tx_power_timeout(void* data) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_read_tx_power_timeout(data);
-}
void btm_rejectlist_role_change_device(const RawAddress& bd_addr, uint8_t hci_status) {
inc_func_call_count(__func__);
test::mock::stack_acl::btm_rejectlist_role_change_device(bd_addr, hci_status);
}
-void btm_set_link_policy(tACL_CONN* conn, tLINK_POLICY policy) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::btm_set_link_policy(conn, policy);
-}
void btm_set_packet_types_from_address(const RawAddress& bd_addr, uint16_t pkt_types) {
inc_func_call_count(__func__);
test::mock::stack_acl::btm_set_packet_types_from_address(bd_addr, pkt_types);
}
-void hci_btm_set_link_supervision_timeout(tACL_CONN& link, uint16_t timeout) {
- inc_func_call_count(__func__);
- test::mock::stack_acl::hci_btm_set_link_supervision_timeout(link, timeout);
-}
void btm_connection_request(const RawAddress& bda, const bluetooth::hci::ClassOfDevice& cod) {
test::mock::stack_acl::btm_connection_request(bda, cod);
}
diff --git a/system/test/mock/mock_stack_acl.h b/system/test/mock/mock_stack_acl.h
index a454f7f..8e123f3 100644
--- a/system/test/mock/mock_stack_acl.h
+++ b/system/test/mock/mock_stack_acl.h
@@ -221,17 +221,6 @@
bool operator()(uint16_t hci_handle, const uint8_t* p) { return body(hci_handle, p); }
};
extern struct acl_set_peer_le_features_from_handle acl_set_peer_le_features_from_handle;
-// Name: acl_get_connection_from_address
-// Params: const RawAddress& bd_addr, tBT_TRANSPORT transport
-// Returns: tACL_CONN*
-struct acl_get_connection_from_address {
- std::function<tACL_CONN*(const RawAddress& bd_addr, tBT_TRANSPORT transport)> body{
- [](const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport */) { return nullptr; }};
- tACL_CONN* operator()(const RawAddress& bd_addr, tBT_TRANSPORT transport) {
- return body(bd_addr, transport);
- }
-};
-extern struct acl_get_connection_from_address acl_get_connection_from_address;
// Name: btm_acl_for_bda
// Params: const RawAddress& bd_addr, tBT_TRANSPORT transport
// Returns: tACL_CONN*
@@ -243,14 +232,6 @@
}
};
extern struct btm_acl_for_bda btm_acl_for_bda;
-// Name: acl_get_connection_from_handle
-// Params: uint16_t handle
-// Returns: tACL_CONN*
-struct acl_get_connection_from_handle {
- std::function<tACL_CONN*(uint16_t handle)> body{[](uint16_t /* handle */) { return nullptr; }};
- tACL_CONN* operator()(uint16_t handle) { return body(handle); }
-};
-extern struct acl_get_connection_from_handle acl_get_connection_from_handle;
// Name: BTM_ReadFailedContactCounter
// Params: const RawAddress& remote_bda, tBTM_CMPL_CB* p_cb
// Returns: tBTM_STATUS
@@ -578,27 +559,6 @@
}
};
extern struct btm_acl_role_changed btm_acl_role_changed;
-// Name: btm_acl_update_conn_addr
-// Params: uint16_t handle, const RawAddress& address
-// Returns: void
-struct btm_acl_update_conn_addr {
- std::function<void(uint16_t handle, const RawAddress& address)> body{
- [](uint16_t /* handle */, const RawAddress& /* address */) { ; }};
- void operator()(uint16_t handle, const RawAddress& address) { body(handle, address); }
-};
-extern struct btm_acl_update_conn_addr btm_acl_update_conn_addr;
-// Name: btm_ble_refresh_local_resolvable_private_addr
-// Params: const RawAddress& pseudo_addr, const RawAddress& local_rpa
-// Returns: void
-struct btm_ble_refresh_local_resolvable_private_addr {
- std::function<void(const RawAddress& pseudo_addr, const RawAddress& local_rpa)> body{
- [](const RawAddress& /* pseudo_addr */, const RawAddress& /* local_rpa */) { ; }};
- void operator()(const RawAddress& pseudo_addr, const RawAddress& local_rpa) {
- body(pseudo_addr, local_rpa);
- }
-};
-extern struct btm_ble_refresh_local_resolvable_private_addr
- btm_ble_refresh_local_resolvable_private_addr;
// Name: btm_cont_rswitch_from_handle
// Params: uint16_t hci_handle
// Returns: void
@@ -616,29 +576,6 @@
void operator()(const RawAddress& bda, tBT_TRANSPORT transport) { body(bda, transport); }
};
extern struct btm_establish_continue_from_address btm_establish_continue_from_address;
-// Name: btm_process_remote_ext_features
-// Params: tACL_CONN* p_acl_cb, uint8_t max_page_number
-// Returns: void
-struct btm_process_remote_ext_features {
- std::function<void(tACL_CONN* p_acl_cb, uint8_t max_page_number)> body{
- [](tACL_CONN* /* p_acl_cb */, uint8_t /* max_page_number */) { ; }};
- void operator()(tACL_CONN* p_acl_cb, uint8_t max_page_number) { body(p_acl_cb, max_page_number); }
-};
-extern struct btm_process_remote_ext_features btm_process_remote_ext_features;
-// Name: btm_process_remote_version_complete
-// Params: uint8_t status, uint16_t handle, uint8_t lmp_version, uint16_t
-// manufacturer, uint16_t lmp_subversion Returns: void
-struct btm_process_remote_version_complete {
- std::function<void(uint8_t status, uint16_t handle, uint8_t lmp_version, uint16_t manufacturer,
- uint16_t lmp_subversion)>
- body{[](uint8_t /* status */, uint16_t /* handle */, uint8_t /* lmp_version */,
- uint16_t /* manufacturer */, uint16_t /* lmp_subversion */) { ; }};
- void operator()(uint8_t status, uint16_t handle, uint8_t lmp_version, uint16_t manufacturer,
- uint16_t lmp_subversion) {
- body(status, handle, lmp_version, manufacturer, lmp_subversion);
- }
-};
-extern struct btm_process_remote_version_complete btm_process_remote_version_complete;
// Name: btm_read_automatic_flush_timeout_complete
// Params: uint8_t* p
// Returns: void
@@ -655,23 +592,6 @@
void operator()(uint8_t* p) { body(p); }
};
extern struct btm_read_failed_contact_counter_complete btm_read_failed_contact_counter_complete;
-// Name: btm_read_failed_contact_counter_timeout
-// Params: void* data
-// Returns: void
-struct btm_read_failed_contact_counter_timeout {
- std::function<void(void* data)> body{[](void* /* data */) { ; }};
- void operator()(void* data) { body(data); }
-};
-extern struct btm_read_failed_contact_counter_timeout btm_read_failed_contact_counter_timeout;
-// Name: btm_read_remote_ext_features
-// Params: uint16_t handle, uint8_t page_number
-// Returns: void
-struct btm_read_remote_ext_features {
- std::function<void(uint16_t handle, uint8_t page_number)> body{
- [](uint16_t /* handle */, uint8_t /* page_number */) { ; }};
- void operator()(uint16_t handle, uint8_t page_number) { body(handle, page_number); }
-};
-extern struct btm_read_remote_ext_features btm_read_remote_ext_features;
// Name: btm_read_remote_ext_features_complete
// Params: uint16_t handle, uint8_t page_num, uint8_t max_page, uint8_t*
// features Returns: void
@@ -725,14 +645,6 @@
void operator()(uint8_t* p, uint16_t evt_len) { body(p, evt_len); }
};
extern struct btm_read_rssi_complete btm_read_rssi_complete;
-// Name: btm_read_rssi_timeout
-// Params: void* data
-// Returns: void
-struct btm_read_rssi_timeout {
- std::function<void(void* data)> body{[](void* /* data */) { ; }};
- void operator()(void* data) { body(data); }
-};
-extern struct btm_read_rssi_timeout btm_read_rssi_timeout;
// Name: btm_read_tx_power_complete
// Params: uint8_t* p, bool is_ble
// Returns: void
@@ -742,14 +654,6 @@
void operator()(uint8_t* p, uint16_t evt_len, bool is_ble) { body(p, evt_len, is_ble); }
};
extern struct btm_read_tx_power_complete btm_read_tx_power_complete;
-// Name: btm_read_tx_power_timeout
-// Params: void* data
-// Returns: void
-struct btm_read_tx_power_timeout {
- std::function<void(void* data)> body{[](void* /* data */) { ; }};
- void operator()(void* data) { body(data); }
-};
-extern struct btm_read_tx_power_timeout btm_read_tx_power_timeout;
// Name: btm_rejectlist_role_change_device
// Params: const RawAddress& bd_addr, uint8_t hci_status
// Returns: void
@@ -759,15 +663,6 @@
void operator()(const RawAddress& bd_addr, uint8_t hci_status) { body(bd_addr, hci_status); }
};
extern struct btm_rejectlist_role_change_device btm_rejectlist_role_change_device;
-// Name: btm_set_link_policy
-// Params: tACL_CONN* conn, tLINK_POLICY policy
-// Returns: void
-struct btm_set_link_policy {
- std::function<void(tACL_CONN* conn, tLINK_POLICY policy)> body{
- [](tACL_CONN* /* conn */, tLINK_POLICY /* policy */) { ; }};
- void operator()(tACL_CONN* conn, tLINK_POLICY policy) { body(conn, policy); }
-};
-extern struct btm_set_link_policy btm_set_link_policy;
// Name: btm_set_packet_types_from_address
// Params: const RawAddress& bd_addr, uint16_t pkt_types
// Returns: void
@@ -777,15 +672,6 @@
void operator()(const RawAddress& bd_addr, uint16_t pkt_types) { body(bd_addr, pkt_types); }
};
extern struct btm_set_packet_types_from_address btm_set_packet_types_from_address;
-// Name: hci_btm_set_link_supervision_timeout
-// Params: tACL_CONN& link, uint16_t timeout
-// Returns: void
-struct hci_btm_set_link_supervision_timeout {
- std::function<void(tACL_CONN& link, uint16_t timeout)> body{
- [](tACL_CONN& /* link */, uint16_t /* timeout */) { ; }};
- void operator()(tACL_CONN& link, uint16_t timeout) { body(link, timeout); }
-};
-extern struct hci_btm_set_link_supervision_timeout hci_btm_set_link_supervision_timeout;
// Name: on_acl_br_edr_connected
// Params: const RawAddress& bda, uint16_t handle, uint8_t enc_mode, bool
// locally_initiated Returns: void
diff --git a/system/test/mock/mock_stack_acl_ble.cc b/system/test/mock/mock_stack_acl_ble.cc
index e403a92..8f888dc 100644
--- a/system/test/mock/mock_stack_acl_ble.cc
+++ b/system/test/mock/mock_stack_acl_ble.cc
@@ -21,15 +21,13 @@
#include <cstdint>
+#include "stack/include/ble_acl_interface.h"
#include "stack/include/hci_error_code.h"
#include "test/common/mock_functions.h"
#include "types/ble_address_with_type.h"
#include "types/hci_role.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
void acl_ble_connection_fail(const tBLE_BD_ADDR& /* address_with_type */, uint16_t /* handle */,
bool /* enhanced */, tHCI_STATUS /* status */) {
inc_func_call_count(__func__);
diff --git a/system/test/mock/mock_stack_acl_btm_pm.cc b/system/test/mock/mock_stack_acl_btm_pm.cc
index 8ae9f01..bc1d3de 100644
--- a/system/test/mock/mock_stack_acl_btm_pm.cc
+++ b/system/test/mock/mock_stack_acl_btm_pm.cc
@@ -22,13 +22,12 @@
#include <cstdint>
#include "stack/btm/power_mode.h"
+#include "stack/include/acl_api.h"
+#include "stack/include/acl_hci_link_interface.h"
#include "stack/include/btm_status.h"
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
bool BTM_ReadPowerMode(const RawAddress& /* remote_bda */, tBTM_PM_MODE* /* p_mode */) {
inc_func_call_count(__func__);
return false;
@@ -81,7 +80,3 @@
inc_func_call_count(__func__);
}
void btm_pm_reset(void) { inc_func_call_count(__func__); }
-void process_ssr_event(tHCI_STATUS /* status */, uint16_t /* handle */, uint16_t /* max_tx_lat */,
- uint16_t /* max_rx_lat */) {
- inc_func_call_count(__func__);
-}
diff --git a/system/test/mock/mock_stack_avrc_api.cc b/system/test/mock/mock_stack_avrc_api.cc
index 655690c..eedf433 100644
--- a/system/test/mock/mock_stack_avrc_api.cc
+++ b/system/test/mock/mock_stack_avrc_api.cc
@@ -77,6 +77,3 @@
}
void avrc_flush_cmd_q(uint8_t /* handle */) { inc_func_call_count(__func__); }
void avrc_send_next_vendor_cmd(uint8_t /* handle */) { inc_func_call_count(__func__); }
-void avrc_start_cmd_timer(uint8_t /* handle */, uint8_t /* label */, uint8_t /* msg_mask */) {
- inc_func_call_count(__func__);
-}
diff --git a/system/test/mock/mock_stack_gap_ble.cc b/system/test/mock/mock_stack_gap_ble.cc
index 941ca7d..3f852ff 100644
--- a/system/test/mock/mock_stack_gap_ble.cc
+++ b/system/test/mock/mock_stack_gap_ble.cc
@@ -21,13 +21,11 @@
#include <cstdint>
+#include "stack/gap/gap_int.h"
#include "stack/include/gap_api.h"
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
bool GAP_BleCancelReadPeerDevName(const RawAddress& /* peer_bda */) {
inc_func_call_count(__func__);
return false;
diff --git a/system/test/mock/mock_stack_gap_conn.cc b/system/test/mock/mock_stack_gap_conn.cc
index 6fb9826..19034a9 100644
--- a/system/test/mock/mock_stack_gap_conn.cc
+++ b/system/test/mock/mock_stack_gap_conn.cc
@@ -24,9 +24,6 @@
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
const RawAddress* GAP_ConnGetRemoteAddr(uint16_t /* gap_handle */) {
inc_func_call_count(__func__);
return nullptr;
@@ -65,6 +62,3 @@
return 0;
}
void GAP_Init(void) { inc_func_call_count(__func__); }
-void gap_tx_complete_ind(uint16_t /* l2cap_cid */, uint16_t /* sdu_sent */) {
- inc_func_call_count(__func__);
-}
diff --git a/system/test/mock/mock_stack_gatt.cc b/system/test/mock/mock_stack_gatt.cc
index 297ec57..a6dfb1d 100644
--- a/system/test/mock/mock_stack_gatt.cc
+++ b/system/test/mock/mock_stack_gatt.cc
@@ -26,17 +26,8 @@
#include "test/common/mock_functions.h"
#include "types/bluetooth/uuid.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
using namespace bluetooth;
-tGATT_HDL_LIST_ELEM elem; // gatt_add_an_item_to_list
-
-tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t /* s_handle */) {
- inc_func_call_count(__func__);
- return elem;
-}
tGATT_STATUS GATTC_Discover(uint16_t /* conn_id */, tGATT_DISC_TYPE /* disc_type */,
uint16_t /* start_handle */, uint16_t /* end_handle */,
const Uuid& /* uuid */) {
diff --git a/system/test/mock/mock_stack_gatt_api.cc b/system/test/mock/mock_stack_gatt_api.cc
index cde6c3f..2822d79 100644
--- a/system/test/mock/mock_stack_gatt_api.cc
+++ b/system/test/mock/mock_stack_gatt_api.cc
@@ -27,9 +27,6 @@
#include "test/common/mock_functions.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
// Original usings
using bluetooth::Uuid;
@@ -66,8 +63,6 @@
struct GATT_Register GATT_Register;
struct GATT_SetIdleTimeout GATT_SetIdleTimeout;
struct GATT_StartIf GATT_StartIf;
-// struct gatt_add_an_item_to_list gatt_add_an_item_to_list;
-struct is_active_service is_active_service;
} // namespace stack_gatt_api
} // namespace mock
@@ -99,9 +94,6 @@
bool GATT_GetConnIdIfConnected::return_value = false;
bool GATT_GetConnectionInfor::return_value = false;
tGATT_IF GATT_Register::return_value = 0;
-// tGATT_HDL_LIST_ELEM gatt_add_an_item_to_list::return_value = { .svc_db = {},
-// .asgn_range = {}};
-bool is_active_service::return_value = false;
} // namespace stack_gatt_api
} // namespace mock
@@ -230,14 +222,6 @@
inc_func_call_count(__func__);
test::mock::stack_gatt_api::GATT_StartIf(gatt_if);
}
-// tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) {
-// inc_func_call_count(__func__);
-// return test::mock::stack_gatt_api::gatt_add_an_item_to_list(s_handle);
-// }
-bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) {
- inc_func_call_count(__func__);
- return test::mock::stack_gatt_api::is_active_service(app_uuid128, p_svc_uuid, start_handle);
-}
// Mocked functions complete
//
bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, tBTM_BLE_CONN_TYPE connection_type,
diff --git a/system/test/mock/mock_stack_gatt_api.h b/system/test/mock/mock_stack_gatt_api.h
index 74bf566..63d4e0f 100644
--- a/system/test/mock/mock_stack_gatt_api.h
+++ b/system/test/mock/mock_stack_gatt_api.h
@@ -398,33 +398,6 @@
};
extern struct GATT_StartIf GATT_StartIf;
-// // Name: gatt_add_an_item_to_list
-// // Params: uint16_t s_handle
-// // Return: tGATT_HDL_LIST_ELEM&
-// struct gatt_add_an_item_to_list {
-// static tGATT_HDL_LIST_ELEM return_value;
-// std::function<tGATT_HDL_LIST_ELEM&(uint16_t s_handle)> body{
-// [](uint16_t s_handle) { return return_value; }};
-// tGATT_HDL_LIST_ELEM& operator()(uint16_t s_handle) { return body(s_handle);
-// };
-// };
-// extern struct gatt_add_an_item_to_list gatt_add_an_item_to_list;
-
-// Name: is_active_service
-// Params: const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle
-// Return: bool
-struct is_active_service {
- static bool return_value;
- std::function<bool(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle)> body{
- [](const Uuid& /* app_uuid128 */, Uuid* /* p_svc_uuid */, uint16_t /* start_handle */) {
- return return_value;
- }};
- bool operator()(const Uuid& app_uuid128, Uuid* p_svc_uuid, uint16_t start_handle) {
- return body(app_uuid128, p_svc_uuid, start_handle);
- }
-};
-extern struct is_active_service is_active_service;
-
} // namespace stack_gatt_api
} // namespace mock
} // namespace test
diff --git a/system/test/mock/mock_stack_gatt_attr.cc b/system/test/mock/mock_stack_gatt_attr.cc
index 6de9539..4e46e87 100644
--- a/system/test/mock/mock_stack_gatt_attr.cc
+++ b/system/test/mock/mock_stack_gatt_attr.cc
@@ -28,15 +28,11 @@
#include "types/bt_transport.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
uint16_t gatt_profile_find_conn_id_by_bd_addr(const RawAddress& /* remote_bda */) {
inc_func_call_count(__func__);
return 0;
}
-bool gatt_profile_get_eatt_support(const RawAddress& /* remote_bda */,
- base::OnceCallback<void(const RawAddress&, bool)> /* cb */) {
+bool gatt_profile_get_eatt_support(const RawAddress& /* remote_bda */) {
inc_func_call_count(__func__);
return false;
}
@@ -48,31 +44,10 @@
inc_func_call_count(__func__);
return false;
}
-tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(uint16_t /* conn_id */, const RawAddress& /* bda */,
- tBT_TRANSPORT /* tranport */) {
- inc_func_call_count(__func__);
- return nullptr;
-}
-tGATT_STATUS proc_read_req(uint16_t /* conn_id */, tGATTS_REQ_TYPE, tGATT_READ_REQ* /* p_data */,
- tGATTS_RSP* /* p_rsp */) {
- inc_func_call_count(__func__);
- return GATT_SUCCESS;
-}
-tGATT_STATUS proc_write_req(uint16_t /* conn_id */, tGATTS_REQ_TYPE,
- tGATT_WRITE_REQ* /* p_data */) {
- inc_func_call_count(__func__);
- return GATT_SUCCESS;
-}
-tGATT_STATUS read_attr_value(uint16_t /* conn_id */, uint16_t /* handle */,
- tGATT_VALUE* /* p_value */, bool /* is_long */) {
- inc_func_call_count(__func__);
- return GATT_SUCCESS;
-}
void GATT_ConfigServiceChangeCCC(const RawAddress& /* remote_bda */, bool /* enable */,
tBT_TRANSPORT /* transport */) {
inc_func_call_count(__func__);
}
-void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* /* p_clcb */) { inc_func_call_count(__func__); }
void gatt_profile_db_init(void) { inc_func_call_count(__func__); }
void gatt_sr_init_cl_status(tGATT_TCB& /* tcb */) { inc_func_call_count(__func__); }
void gatt_sr_update_cl_status(tGATT_TCB& /* tcb */, bool /* chg_aware */) {
diff --git a/system/test/mock/mock_stack_gatt_auth.cc b/system/test/mock/mock_stack_gatt_auth.cc
index 1e59e81..0351bf3 100644
--- a/system/test/mock/mock_stack_gatt_auth.cc
+++ b/system/test/mock/mock_stack_gatt_auth.cc
@@ -26,17 +26,10 @@
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
bool gatt_security_check_start(tGATT_CLCB* /* p_clcb */) {
inc_func_call_count(__func__);
return false;
}
-tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* /* p_clcb */) {
- inc_func_call_count(__func__);
- return GATT_SEC_NONE;
-}
tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* /* p_tcb */) {
inc_func_call_count(__func__);
return GATT_SEC_NONE;
diff --git a/system/test/mock/mock_stack_gatt_main.cc b/system/test/mock/mock_stack_gatt_main.cc
index 8ef0677..2c09b4a 100644
--- a/system/test/mock/mock_stack_gatt_main.cc
+++ b/system/test/mock/mock_stack_gatt_main.cc
@@ -21,13 +21,11 @@
#include "stack/gatt/gatt_int.h"
#include "stack/include/bt_hdr.h"
+#include "stack/include/gatt_api.h"
#include "stack/include/l2cap_interface.h"
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
void gatt_init(void) { inc_func_call_count(__func__); }
bool gatt_act_connect(tGATT_REG* /* p_reg */, const RawAddress& /* bd_addr */,
tBLE_ADDR_TYPE /* addr_type */, tBT_TRANSPORT /* transport */,
@@ -35,12 +33,6 @@
inc_func_call_count(__func__);
return false;
}
-bool gatt_connect(const RawAddress& /* rem_bda */, tGATT_TCB* /* p_tcb */,
- tBLE_ADDR_TYPE /* addr_type */, tBT_TRANSPORT /* transport */,
- uint8_t /* initiating_phys */, tGATT_IF /* gatt_if */) {
- inc_func_call_count(__func__);
- return false;
-}
void gatt_cancel_connect(const RawAddress& /* bd_addr */, tBT_TRANSPORT /* transport*/) {
inc_func_call_count(__func__);
}
@@ -64,16 +56,6 @@
}
void gatt_free(void) { inc_func_call_count(__func__); }
void gatt_init_srv_chg(void) { inc_func_call_count(__func__); }
-void gatt_l2cif_config_cfm_cback(uint16_t /* lcid */, uint16_t /* initiator */,
- tL2CAP_CFG_INFO* /* p_cfg */) {
- inc_func_call_count(__func__);
-}
-void gatt_l2cif_config_ind_cback(uint16_t /* lcid */, tL2CAP_CFG_INFO* /* p_cfg */) {
- inc_func_call_count(__func__);
-}
-void gatt_l2cif_disconnect_ind_cback(uint16_t /* lcid */, bool /* ack_needed */) {
- inc_func_call_count(__func__);
-}
void gatt_notify_conn_update(const RawAddress& /* remote */, uint16_t /* interval */,
uint16_t /* latency */, uint16_t /* timeout */,
tHCI_STATUS /* status */) {
diff --git a/system/test/mock/mock_stack_smp_act.cc b/system/test/mock/mock_stack_smp_act.cc
index 486cf5d..2802fb6 100644
--- a/system/test/mock/mock_stack_smp_act.cc
+++ b/system/test/mock/mock_stack_smp_act.cc
@@ -26,15 +26,13 @@
#include <cstdint>
// Original included files, if any
+#include "stack/include/smp_api.h"
#include "test/common/mock_functions.h"
#include "types/raw_address.h"
// Mocked compile conditionals, if any
// Mocked internal structures, if any
-// TODO(b/369381361) Enfore -Wmissing-prototypes
-#pragma GCC diagnostic ignored "-Wmissing-prototypes"
-
namespace test {
namespace mock {
namespace stack_smp_act {
diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp
index 09e8fda..d495cc0 100644
--- a/system/test/suite/Android.bp
+++ b/system/test/suite/Android.bp
@@ -120,6 +120,7 @@
"gatt/gatt_unittest.cc",
],
static_libs: [
+ "aics",
"bluetooth_flags_c_lib_for_test",
"libbluetooth_crypto_toolbox",
"libbluetooth_gd",
@@ -133,9 +134,13 @@
"libflags_rust_cpp_bridge",
"libprotobuf-cpp-lite",
],
+ aidl: {
+ libs: ["bluetooth_constants"],
+ },
shared_libs: [
"libaconfig_storage_read_api_cc",
"libbase",
+ "libbinder",
"server_configurable_flags",
],
generated_headers: [