Merge "broadcastradio 2.0: uses correct interface tag."
diff --git a/audio/7.1/config/api/current.txt b/audio/7.1/config/api/current.txt
index 2963904..75fc5c0 100644
--- a/audio/7.1/config/api/current.txt
+++ b/audio/7.1/config/api/current.txt
@@ -86,6 +86,7 @@
enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_MUSIC;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_SONIFICATION;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_SPEECH;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_ULTRASOUND;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioContentType AUDIO_CONTENT_TYPE_UNKNOWN;
}
@@ -273,6 +274,7 @@
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_MMAP_NOIRQ;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_RAW;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_SYNC;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_ULTRASOUND;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_INPUT_FLAG_VOIP_TX;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
@@ -290,6 +292,7 @@
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SPATIALIZER;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_SYNC;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_TTS;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_ULTRASOUND;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioInOutFlag AUDIO_OUTPUT_FLAG_VOIP_RX;
}
@@ -314,6 +317,7 @@
enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_HOTWORD;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_MIC;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_REMOTE_SUBMIX;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_ULTRASOUND;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_UNPROCESSED;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_CALL;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioSource AUDIO_SOURCE_VOICE_COMMUNICATION;
@@ -355,6 +359,7 @@
enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_GAME;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_MEDIA;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION;
+ enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION_EVENT;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_SAFETY;
enum_constant public static final android.audio.policy.configuration.V7_1.AudioUsage AUDIO_USAGE_UNKNOWN;
diff --git a/audio/7.1/config/audio_policy_configuration.xsd b/audio/7.1/config/audio_policy_configuration.xsd
index 414552e..7e1da90 100644
--- a/audio/7.1/config/audio_policy_configuration.xsd
+++ b/audio/7.1/config/audio_policy_configuration.xsd
@@ -180,6 +180,7 @@
<xs:enumeration value="AUDIO_OUTPUT_FLAG_INCALL_MUSIC" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD" />
<xs:enumeration value="AUDIO_OUTPUT_FLAG_SPATIALIZER" />
+ <xs:enumeration value="AUDIO_OUTPUT_FLAG_ULTRASOUND" />
<xs:enumeration value="AUDIO_INPUT_FLAG_FAST" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_HOTWORD" />
<xs:enumeration value="AUDIO_INPUT_FLAG_RAW" />
@@ -188,6 +189,7 @@
<xs:enumeration value="AUDIO_INPUT_FLAG_VOIP_TX" />
<xs:enumeration value="AUDIO_INPUT_FLAG_HW_AV_SYNC" />
<xs:enumeration value="AUDIO_INPUT_FLAG_DIRECT" />
+ <xs:enumeration value="AUDIO_INPUT_FLAG_ULTRASOUND" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="audioInOutFlags">
@@ -441,6 +443,7 @@
<xs:enumeration value="AUDIO_USAGE_ALARM" />
<xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
<xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+ <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_EVENT" />
<xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
<xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
<xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
@@ -471,6 +474,7 @@
<xs:enumeration value="AUDIO_CONTENT_TYPE_MUSIC"/>
<xs:enumeration value="AUDIO_CONTENT_TYPE_MOVIE"/>
<xs:enumeration value="AUDIO_CONTENT_TYPE_SONIFICATION"/>
+ <xs:enumeration value="AUDIO_CONTENT_TYPE_ULTRASOUND"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="samplingRates">
@@ -742,6 +746,7 @@
<xs:enumeration value="AUDIO_SOURCE_ECHO_REFERENCE"/>
<xs:enumeration value="AUDIO_SOURCE_FM_TUNER"/>
<xs:enumeration value="AUDIO_SOURCE_HOTWORD"/>
+ <xs:enumeration value="AUDIO_SOURCE_ULTRASOUND"/>
</xs:restriction>
</xs:simpleType>
<!-- Enum values of device_category from Volume.h. -->
diff --git a/audio/common/all-versions/default/7.0/HidlUtils.cpp b/audio/common/all-versions/default/7.0/HidlUtils.cpp
index 218d7c0..0fd2947 100644
--- a/audio/common/all-versions/default/7.0/HidlUtils.cpp
+++ b/audio/common/all-versions/default/7.0/HidlUtils.cpp
@@ -485,8 +485,12 @@
status_t HidlUtils::audioUsageFromHal(audio_usage_t halUsage, AudioUsage* usage) {
if (halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST ||
halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT ||
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED) {
+#else
halUsage == AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED ||
halUsage == AUDIO_USAGE_NOTIFICATION_EVENT) {
+#endif
halUsage = AUDIO_USAGE_NOTIFICATION;
}
*usage = audio_usage_to_string(halUsage);
diff --git a/audio/common/all-versions/default/Android.bp b/audio/common/all-versions/default/Android.bp
index 8f55744..a25565d 100644
--- a/audio/common/all-versions/default/Android.bp
+++ b/audio/common/all-versions/default/Android.bp
@@ -157,6 +157,28 @@
],
}
+cc_library {
+ name: "android.hardware.audio.common@7.1-util",
+ defaults: ["android.hardware.audio.common-util_default"],
+ srcs: [
+ "7.0/HidlUtils.cpp",
+ "HidlUtilsCommon.cpp",
+ "UuidUtils.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "libbase",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
// Note: this isn't a VTS test, but rather a unit test
// to verify correctness of conversion utilities.
cc_test {
@@ -214,3 +236,35 @@
test_suites: ["device-tests"],
}
+
+cc_test {
+ name: "android.hardware.audio.common@7.1-util_tests",
+ defaults: ["android.hardware.audio.common-util_default"],
+
+ srcs: ["tests/hidlutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.1.
+ static_libs: [
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "android.hardware.audio.common@7.0",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/common/all-versions/default/HidlUtilsCommon.cpp b/audio/common/all-versions/default/HidlUtilsCommon.cpp
index d2da193..bc3d870 100644
--- a/audio/common/all-versions/default/HidlUtilsCommon.cpp
+++ b/audio/common/all-versions/default/HidlUtilsCommon.cpp
@@ -20,7 +20,7 @@
namespace hardware {
namespace audio {
namespace common {
-namespace CPP_VERSION {
+namespace COMMON_TYPES_CPP_VERSION {
namespace implementation {
status_t HidlUtils::audioPortConfigsFromHal(unsigned int numHalConfigs,
@@ -51,7 +51,7 @@
}
} // namespace implementation
-} // namespace CPP_VERSION
+} // namespace COMMON_TYPES_CPP_VERSION
} // namespace common
} // namespace audio
} // namespace hardware
diff --git a/audio/common/all-versions/default/TEST_MAPPING b/audio/common/all-versions/default/TEST_MAPPING
index c965113..780beea 100644
--- a/audio/common/all-versions/default/TEST_MAPPING
+++ b/audio/common/all-versions/default/TEST_MAPPING
@@ -5,6 +5,9 @@
},
{
"name": "android.hardware.audio.common@7.0-util_tests"
+ },
+ {
+ "name": "android.hardware.audio.common@7.1-util_tests"
}
]
}
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 1bd6abe..9890be2 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -52,6 +52,7 @@
shared_libs: [
"libcutils",
"libbinder",
+ "libbinder_ndk",
"libhidlbase",
"liblog",
"libutils",
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index e26369f..fbf6165 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,8 +20,10 @@
#include <string>
#include <vector>
+#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
+#include <dlfcn.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/LegacySupport.h>
#include <hwbinder/ProcessState.h>
@@ -45,6 +47,31 @@
return false;
}
+static bool registerExternalServiceImplementation(const std::string& libName,
+ const std::string& funcName) {
+ constexpr int dlMode = RTLD_LAZY;
+ void* handle = nullptr;
+ dlerror(); // clear
+ auto libPath = libName + ".so";
+ handle = dlopen(libPath.c_str(), dlMode);
+ if (handle == nullptr) {
+ const char* error = dlerror();
+ ALOGE("Failed to dlopen %s: %s", libPath.c_str(),
+ error != nullptr ? error : "unknown error");
+ return false;
+ }
+ binder_status_t (*factoryFunction)();
+ *(void**)(&factoryFunction) = dlsym(handle, funcName.c_str());
+ if (!factoryFunction) {
+ const char* error = dlerror();
+ ALOGE("Factory function %s not found in libName %s: %s", funcName.c_str(), libPath.c_str(),
+ error != nullptr ? error : "unknown error");
+ dlclose(handle);
+ return false;
+ }
+ return ((*factoryFunction)() == STATUS_OK);
+}
+
int main(int /* argc */, char* /* argv */ []) {
signal(SIGPIPE, SIG_IGN);
@@ -52,6 +79,9 @@
// start a threadpool for vndbinder interactions
::android::ProcessState::self()->startThreadPool();
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
const int32_t defaultValue = -1;
int32_t value =
property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
@@ -101,6 +131,13 @@
"android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload"
}
};
+
+ const std::vector<std::pair<std::string,std::string>> optionalInterfaceSharedLibs = {
+ {
+ "android.hardware.bluetooth.audio-impl",
+ "createIBluetoothAudioProviderFactory",
+ },
+ };
// clang-format on
for (const auto& listIter : mandatoryInterfaces) {
@@ -117,5 +154,15 @@
"Could not register %s", interfaceFamilyName.c_str());
}
+ for (const auto& interfacePair : optionalInterfaceSharedLibs) {
+ const std::string& libraryName = interfacePair.first;
+ const std::string& interfaceLoaderFuncName = interfacePair.second;
+ if (registerExternalServiceImplementation(libraryName, interfaceLoaderFuncName)) {
+ ALOGI("%s() from %s success", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+ } else {
+ ALOGW("%s() from %s failed", interfaceLoaderFuncName.c_str(), libraryName.c_str());
+ }
+ }
+
joinRpcThreadpool();
}
diff --git a/audio/common/all-versions/default/tests/hidlutils_tests.cpp b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
index 2749cce..ec16b02 100644
--- a/audio/common/all-versions/default/tests/hidlutils_tests.cpp
+++ b/audio/common/all-versions/default/tests/hidlutils_tests.cpp
@@ -23,7 +23,7 @@
#include <log/log.h>
#include <HidlUtils.h>
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
#include <system/audio.h>
#include <xsdc/XsdcSupport.h>
@@ -32,7 +32,7 @@
using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index df688fd..3536561 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -168,10 +168,10 @@
shared_libs: [
"android.hardware.audio@7.0",
"android.hardware.audio@7.1",
- "android.hardware.audio@7.0-util",
+ "android.hardware.audio@7.1-util",
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.1-enums",
- "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio.common@7.1-util",
"libbase",
],
cflags: [
diff --git a/audio/core/all-versions/default/TEST_MAPPING b/audio/core/all-versions/default/TEST_MAPPING
index 1e29440..07e98f3 100644
--- a/audio/core/all-versions/default/TEST_MAPPING
+++ b/audio/core/all-versions/default/TEST_MAPPING
@@ -4,6 +4,9 @@
"name": "android.hardware.audio@7.0-util_tests"
},
{
+ "name": "android.hardware.audio@7.1-util_tests"
+ },
+ {
"name": "HalAudioV6_0GeneratorTest"
},
{
diff --git a/audio/core/all-versions/default/util/Android.bp b/audio/core/all-versions/default/util/Android.bp
index 7caf18d..b96f2d2 100644
--- a/audio/core/all-versions/default/util/Android.bp
+++ b/audio/core/all-versions/default/util/Android.bp
@@ -112,6 +112,25 @@
],
}
+cc_library {
+ name: "android.hardware.audio@7.1-util",
+ defaults: ["android.hardware.audio-util_default"],
+ shared_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "android.hardware.audio@7.1",
+ "libbase",
+ ],
+ cflags: [
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+}
+
// Note: this isn't a VTS test, but rather a unit test
// to verify correctness of conversion utilities.
cc_test {
@@ -145,3 +164,37 @@
test_suites: ["device-tests"],
}
+
+cc_test {
+ name: "android.hardware.audio@7.1-util_tests",
+ defaults: ["android.hardware.audio-util_default"],
+
+ srcs: ["tests/coreutils_tests.cpp"],
+
+ // Use static linking to allow running in presubmit on
+ // targets that don't have HAL V7.1.
+ static_libs: [
+ "android.hardware.audio.common@7.0",
+ "android.hardware.audio.common@7.1-enums",
+ "android.hardware.audio.common@7.1-util",
+ "android.hardware.audio@7.1",
+ "android.hardware.audio@7.1-util",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DMAJOR_VERSION=7",
+ "-DMINOR_VERSION=1",
+ "-DCOMMON_TYPES_MINOR_VERSION=0",
+ "-DCORE_TYPES_MINOR_VERSION=0",
+ "-include common/all-versions/VersionMacro.h",
+ ],
+
+ test_suites: ["device-tests"],
+}
diff --git a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
index 3976b08..0e15960 100644
--- a/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
+++ b/audio/core/all-versions/default/util/tests/coreutils_tests.cpp
@@ -22,18 +22,18 @@
#define LOG_TAG "CoreUtils_Test"
#include <log/log.h>
-#include <android_audio_policy_configuration_V7_0-enums.h>
+#include PATH(APM_XSD_ENUMS_H_FILENAME)
#include <system/audio.h>
#include <util/CoreUtils.h>
#include <xsdc/XsdcSupport.h>
using namespace android;
using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
-using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
using ::android::hardware::hidl_vec;
-using ::android::hardware::audio::CPP_VERSION::implementation::CoreUtils;
+using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
namespace xsd {
-using namespace ::android::audio::policy::configuration::V7_0;
+using namespace ::android::audio::policy::configuration::CPP_VERSION;
}
static constexpr audio_channel_mask_t kInvalidHalChannelMask = AUDIO_CHANNEL_INVALID;
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index a9797bb..7f4a777 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -28,8 +28,7 @@
if (getDeviceName() != DeviceManager::kPrimaryDevice) {
GTEST_SKIP() << "No primary device on this factory"; // returns
}
- EXPECT_TRUE(
- DeviceManager::getInstance().reset(getFactoryName(), DeviceManager::kPrimaryDevice));
+ EXPECT_TRUE(DeviceManager::getInstance().resetPrimary(getFactoryName()));
// Must use IDevicesFactory directly because DeviceManager always uses
// the latest interfaces version and corresponding methods for opening
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index d810c55..0370895 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -195,7 +195,7 @@
"android.hardware.audio.common@7.0",
"android.hardware.audio.common@7.0-enums",
"android.hardware.audio.common@7.1-enums",
- "android.hardware.audio.common@7.0-util",
+ "android.hardware.audio.common@7.1-util",
],
cflags: [
"-DMAJOR_VERSION=7",
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index c8e0167..6bb39ed 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -96,40 +96,83 @@
}
};
-using FactoryAndDevice = std::tuple<std::string, std::string>;
-class DeviceManager : public InterfaceManager<DeviceManager, FactoryAndDevice, IDevice> {
+namespace impl {
+
+class PrimaryDeviceManager
+ : public InterfaceManager<PrimaryDeviceManager, std::string, IPrimaryDevice> {
public:
- static DeviceManager& getInstance() {
- static DeviceManager instance;
- return instance;
+ static sp<IPrimaryDevice> createInterfaceInstance(const std::string& factoryName) {
+ sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
+ return openPrimaryDevice(factory);
}
+
+ bool reset(const std::string& factoryName) __attribute__((warn_unused_result)) {
+#if MAJOR_VERSION <= 5
+ return InterfaceManager::reset(factoryName, true);
+#elif MAJOR_VERSION >= 6
+ {
+ sp<IPrimaryDevice> device = getExisting(factoryName);
+ if (device != nullptr) {
+ auto ret = device->close();
+ ALOGE_IF(!ret.isOk(), "PrimaryDevice %s close failed: %s", factoryName.c_str(),
+ ret.description().c_str());
+ }
+ }
+ return InterfaceManager::reset(factoryName, false);
+#endif
+ }
+
+ private:
+ static sp<IPrimaryDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) {
+ if (factory == nullptr) return {};
+ Result result;
+ sp<IPrimaryDevice> primaryDevice;
+#if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1)
+ sp<IDevice> device;
+#if MAJOR_VERSION == 2
+ auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device));
+ if (ret.isOk() && result == Result::OK && device != nullptr) {
+ primaryDevice = IPrimaryDevice::castFrom(device);
+ }
+#elif MAJOR_VERSION >= 4
+ auto ret = factory->openPrimaryDevice(returnIn(result, device));
+ if (ret.isOk() && result == Result::OK && device != nullptr) {
+ primaryDevice = IPrimaryDevice::castFrom(device);
+ }
+#endif
+ if (!ret.isOk() || result != Result::OK || primaryDevice == nullptr) {
+ ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p",
+ ret.description().c_str(), result, device.get());
+ return nullptr;
+ }
+#else // V7.1
+ auto ret = factory->openPrimaryDevice_7_1(returnIn(result, primaryDevice));
+ if (!ret.isOk() || result != Result::OK) {
+ ALOGW("Primary device can not be opened, transaction: %s, result %d",
+ ret.description().c_str(), result);
+ return nullptr;
+ }
+#endif
+ return primaryDevice;
+ }
+};
+
+using FactoryAndDevice = std::tuple<std::string, std::string>;
+class RegularDeviceManager
+ : public InterfaceManager<RegularDeviceManager, FactoryAndDevice, IDevice> {
+ public:
static sp<IDevice> createInterfaceInstance(const FactoryAndDevice& factoryAndDevice) {
auto [factoryName, name] = factoryAndDevice;
sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
return openDevice(factory, name);
}
- using InterfaceManager::reset;
-
- static constexpr const char* kPrimaryDevice = "primary";
sp<IDevice> get(const std::string& factoryName, const std::string& name) {
- if (name == kPrimaryDevice) {
- (void)getPrimary(factoryName); // for initializing primaryDevice if needed.
- }
return InterfaceManager::get(std::make_tuple(factoryName, name));
}
- sp<IPrimaryDevice> getPrimary(const std::string& factoryName) {
- if (primaryDevice == nullptr) {
- sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName);
- primaryDevice = openPrimaryDevice(factory);
- }
- return primaryDevice;
- }
+
bool reset(const std::string& factoryName, const std::string& name)
__attribute__((warn_unused_result)) {
- if (name == kPrimaryDevice) {
- primaryDevice.clear();
- }
#if MAJOR_VERSION <= 5
return InterfaceManager::reset(std::make_tuple(factoryName, name), true);
#elif MAJOR_VERSION >= 6
@@ -144,9 +187,6 @@
return InterfaceManager::reset(std::make_tuple(factoryName, name), false);
#endif
}
- bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
- return reset(factoryName, kPrimaryDevice);
- }
private:
static sp<IDevice> openDevice(const sp<IDevicesFactory>& factory, const std::string& name) {
@@ -155,9 +195,7 @@
sp<IDevice> device;
#if MAJOR_VERSION == 2
IDevicesFactory::Device dev = IDevicesFactory::IDevicesFactory::Device(-1);
- if (name == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
- dev = IDevicesFactory::Device::PRIMARY;
- } else if (name == AUDIO_HARDWARE_MODULE_ID_A2DP) {
+ if (name == AUDIO_HARDWARE_MODULE_ID_A2DP) {
dev = IDevicesFactory::Device::A2DP;
} else if (name == AUDIO_HARDWARE_MODULE_ID_USB) {
dev = IDevicesFactory::Device::USB;
@@ -179,47 +217,62 @@
}
return device;
}
+};
- static sp<IPrimaryDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) {
- if (factory == nullptr) return {};
- Result result;
- sp<IDevice> device;
- sp<IPrimaryDevice> primaryDevice;
-#if MAJOR_VERSION == 2
- auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device));
- if (ret.isOk() && result == Result::OK && device != nullptr) {
- primaryDevice = IPrimaryDevice::castFrom(device);
+} // namespace impl
+
+class DeviceManager {
+ public:
+ static DeviceManager& getInstance() {
+ static DeviceManager instance;
+ return instance;
+ }
+
+ static constexpr const char* kPrimaryDevice = "primary";
+
+ sp<IDevice> get(const std::string& factoryName, const std::string& name) {
+ if (name == kPrimaryDevice) {
+ auto primary = getPrimary(factoryName);
+ return primary ? deviceFromPrimary(primary) : nullptr;
}
-#elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0))
- auto ret = factory->openPrimaryDevice(returnIn(result, device));
- if (ret.isOk() && result == Result::OK && device != nullptr) {
- primaryDevice = IPrimaryDevice::castFrom(device);
- }
-#elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
- auto ret = factory->openPrimaryDevice_7_1(returnIn(result, primaryDevice));
- if (ret.isOk() && result == Result::OK && primaryDevice != nullptr) {
- auto getDeviceRet = primaryDevice->getDevice();
- if (getDeviceRet.isOk()) {
- device = getDeviceRet;
- } else {
- primaryDevice.clear();
- ALOGW("Primary device can not downcast, transaction: %s, primary %p",
- getDeviceRet.description().c_str(), primaryDevice.get());
- return {};
- }
- }
-#endif
- if (!ret.isOk() || result != Result::OK || device == nullptr) {
- ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p",
- ret.description().c_str(), result, device.get());
- return {};
- }
- return primaryDevice;
+ return mDevices.get(factoryName, name);
+ }
+
+ sp<IPrimaryDevice> getPrimary(const std::string& factoryName) {
+ return mPrimary.get(factoryName);
+ }
+
+ bool reset(const std::string& factoryName, const std::string& name)
+ __attribute__((warn_unused_result)) {
+ return name == kPrimaryDevice ? resetPrimary(factoryName)
+ : mDevices.reset(factoryName, name);
+ }
+
+ bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
+ return mPrimary.reset(factoryName);
+ }
+
+ static void waitForInstanceDestruction() {
+ // Does not matter which device manager to use.
+ impl::RegularDeviceManager::waitForInstanceDestruction();
}
private:
- // There can only be one primary device across all HAL modules.
- // A reference to a complete interface is used because in V7.1 IDevice can not
- // be upcasted to IPrimaryDevice.
- sp<IPrimaryDevice> primaryDevice;
+ sp<IDevice> deviceFromPrimary(const sp<IPrimaryDevice>& primary) {
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ auto ret = primary->getDevice();
+ if (ret.isOk()) {
+ return ret;
+ } else {
+ ALOGW("Error retrieving IDevice from primary: transaction: %s, primary %p",
+ ret.description().c_str(), primary.get());
+ return nullptr;
+ }
+#else
+ return primary;
+#endif
+ }
+
+ impl::PrimaryDeviceManager mPrimary;
+ impl::RegularDeviceManager mDevices;
};
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index cc3c641..0033fee 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -41,5 +41,4 @@
void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
void updateSinkMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
void setLatencyMode(in android.hardware.bluetooth.audio.LatencyMode latencyMode);
- void setCodecType(in android.hardware.bluetooth.audio.CodecType codecType);
}
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index 6e0bd98..267af0f 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -35,7 +35,7 @@
@VintfStability
interface IBluetoothAudioProvider {
void endSession();
- android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
+ android.hardware.common.fmq.MQDescriptor<byte,android.hardware.common.fmq.SynchronizedReadWrite> startSession(in android.hardware.bluetooth.audio.IBluetoothAudioPort hostIf, in android.hardware.bluetooth.audio.AudioConfiguration audioConfig, in android.hardware.bluetooth.audio.LatencyMode[] supportedLatencyModes);
void streamStarted(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
void streamSuspended(in android.hardware.bluetooth.audio.BluetoothAudioStatus status);
void updateAudioConfiguration(in android.hardware.bluetooth.audio.AudioConfiguration audioConfig);
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index 81c2ce2..9f8007b 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -87,11 +87,4 @@
* @param latencyMode latency mode from audio
*/
void setLatencyMode(in LatencyMode latencyMode);
-
- /**
- * Called when codec type is changed.
- *
- * @param codecType codec type from audio
- */
- void setCodecType(in CodecType codecType);
}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
index ca6f691..d5c051e 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.aidl
@@ -19,6 +19,7 @@
import android.hardware.bluetooth.audio.AudioConfiguration;
import android.hardware.bluetooth.audio.BluetoothAudioStatus;
import android.hardware.bluetooth.audio.IBluetoothAudioPort;
+import android.hardware.bluetooth.audio.LatencyMode;
import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
@@ -50,6 +51,8 @@
* device. The PCM parameters are set if software based encoding,
* otherwise the correct codec configuration is used for hardware
* encoding.
+ * @param supportedLatencyModes latency modes supported by the active
+ * remote device
*
* @return The fast message queue for audio data from/to this
* provider. Audio data will be in PCM format as specified by the
@@ -57,8 +60,8 @@
* from/to hardware or on failure
*/
MQDescriptor<byte, SynchronizedReadWrite> startSession(
- in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig);
-
+ in IBluetoothAudioPort hostIf, in AudioConfiguration audioConfig,
+ in LatencyMode[] supportedLatencyModes);
/**
* Callback for IBluetoothAudioPort.startStream()
*
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
index fc8a911..866776e 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -38,7 +38,10 @@
ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return) {
+ latency_modes_ = latency_modes;
if (audio_config.getTag() != AudioConfiguration::a2dpConfig) {
LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
<< audio_config.toString();
@@ -52,8 +55,8 @@
*_aidl_return = DataMQDesc();
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return BluetoothAudioProvider::startSession(host_if, audio_config,
- _aidl_return);
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
}
ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
index 5934f5b..4621e85 100644
--- a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -32,7 +32,9 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
private:
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
index 5a413e0..d2f58f3 100644
--- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -61,7 +61,10 @@
ndk::ScopedAStatus A2dpSoftwareAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return) {
+ latency_modes_ = latency_modes;
if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
<< audio_config.toString();
@@ -77,8 +80,8 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return BluetoothAudioProvider::startSession(host_if, audio_config,
- _aidl_return);
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
}
ndk::ScopedAStatus A2dpSoftwareAudioProvider::onSessionReady(
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
index 3bc0a13..10f533a 100644
--- a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
@@ -32,7 +32,9 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
private:
// audio data queue for software encoding
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
index 8090d26..0dd8148 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -34,11 +34,15 @@
ndk::ScopedAStatus BluetoothAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latencyModes,
+ DataMQDesc* _aidl_return) {
if (host_if == nullptr) {
*_aidl_return = DataMQDesc();
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
+
+ latency_modes_ = latencyModes;
audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
stack_iface_ = host_if;
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
index 393aaba..75794e8 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -16,6 +16,7 @@
#pragma once
#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/LatencyMode.h>
#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
#include <fmq/AidlMessageQueue.h>
@@ -37,10 +38,11 @@
class BluetoothAudioProvider : public BnBluetoothAudioProvider {
public:
BluetoothAudioProvider();
-
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
ndk::ScopedAStatus endSession();
ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
@@ -59,6 +61,7 @@
std::shared_ptr<IBluetoothAudioPort> stack_iface_;
std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
SessionType session_type_;
+ std::vector<LatencyMode> latency_modes_;
};
} // namespace audio
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
index 66ce93b..c754849 100644
--- a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -56,7 +56,10 @@
ndk::ScopedAStatus HearingAidAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return) {
+ latency_modes_ = latency_modes;
if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
<< audio_config.toString();
@@ -71,8 +74,8 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return BluetoothAudioProvider::startSession(host_if, audio_config,
- _aidl_return);
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
}
ndk::ScopedAStatus HearingAidAudioProvider::onSessionReady(
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
index a7e19e9..a158c86 100644
--- a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
@@ -32,7 +32,9 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
private:
// audio data queue for software encoding
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
index 7a28513..1a3c658 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -53,7 +53,10 @@
ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return) {
+ latency_modes_ = latency_modes;
if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
<< audio_config.toString();
@@ -70,8 +73,8 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return BluetoothAudioProvider::startSession(host_if, audio_config,
- _aidl_return);
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
}
ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
index 6509a9e..614c794 100644
--- a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -32,7 +32,9 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
private:
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
index 0fe205e..1f64b43 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -69,7 +69,10 @@
ndk::ScopedAStatus LeAudioSoftwareAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return) {
+ latency_modes_ = latency_modes;
if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
<< audio_config.toString();
@@ -119,8 +122,8 @@
}
data_mq_ = std::move(temp_data_mq);
- return BluetoothAudioProvider::startSession(host_if, audio_config,
- _aidl_return);
+ return BluetoothAudioProvider::startSession(
+ host_if, audio_config, latency_modes, _aidl_return);
}
ndk::ScopedAStatus LeAudioSoftwareAudioProvider::onSessionReady(
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
index ace4bff..21243ff 100644
--- a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
@@ -32,7 +32,9 @@
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
- const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+ const AudioConfiguration& audio_config,
+ const std::vector<LatencyMode>& latency_modes,
+ DataMQDesc* _aidl_return);
private:
// audio data queue for software encoding
diff --git a/bluetooth/audio/aidl/vts/Android.bp b/bluetooth/audio/aidl/vts/Android.bp
new file mode 100644
index 0000000..a662aaa
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/Android.bp
@@ -0,0 +1,31 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalBluetoothAudioTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalBluetoothAudioTargetTest.cpp"],
+ shared_libs: [
+ "android.hardware.audio.common-V1-ndk",
+ "android.hardware.bluetooth.audio-V1-ndk",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libfmq",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
new file mode 100644
index 0000000..e68c654
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -0,0 +1,1673 @@
+/*
+ * Copyright (C) 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.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioPort.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include <cstdint>
+#include <future>
+#include <unordered_set>
+#include <vector>
+
+using aidl::android::hardware::audio::common::SinkMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::bluetooth::audio::AacCapabilities;
+using aidl::android::hardware::bluetooth::audio::AacConfiguration;
+using aidl::android::hardware::bluetooth::audio::AptxCapabilities;
+using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
+using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
+using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
+using aidl::android::hardware::bluetooth::audio::ChannelMode;
+using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
+using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::CodecType;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
+using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
+using aidl::android::hardware::bluetooth::audio::LatencyMode;
+using aidl::android::hardware::bluetooth::audio::Lc3Capabilities;
+using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
+using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
+using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
+using aidl::android::hardware::bluetooth::audio::
+ LeAudioCodecCapabilitiesSetting;
+using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
+using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using aidl::android::hardware::bluetooth::audio::PresentationPosition;
+using aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
+using aidl::android::hardware::bluetooth::audio::SbcCapabilities;
+using aidl::android::hardware::bluetooth::audio::SbcChannelMode;
+using aidl::android::hardware::bluetooth::audio::SbcConfiguration;
+using aidl::android::hardware::bluetooth::audio::SessionType;
+using aidl::android::hardware::bluetooth::audio::UnicastCapability;
+using aidl::android::hardware::common::fmq::MQDescriptor;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using android::AidlMessageQueue;
+using android::ProcessState;
+using android::String16;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
+
+using MqDataType = int8_t;
+using MqDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
+using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+
+// Constants
+
+static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
+static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
+static constexpr ChannelMode a2dp_channel_modes[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+static constexpr CodecType a2dp_codec_types[] = {
+ CodecType::UNKNOWN, CodecType::SBC, CodecType::AAC,
+ CodecType::APTX, CodecType::APTX_HD, CodecType::LDAC,
+ CodecType::LC3, CodecType::APTX_ADAPTIVE};
+static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
+// Helpers
+
+template <typename T>
+struct identity {
+ typedef T type;
+};
+
+template <class T>
+bool contained_in_vector(const std::vector<T>& vector,
+ const typename identity<T>::type& target) {
+ return std::find(vector.begin(), vector.end(), target) != vector.end();
+}
+
+void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
+ const CodecConfiguration::CodecSpecific& src) {
+ switch (src.getTag()) {
+ case CodecConfiguration::CodecSpecific::sbcConfig:
+ dst.set<CodecConfiguration::CodecSpecific::sbcConfig>(
+ src.get<CodecConfiguration::CodecSpecific::sbcConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::aacConfig:
+ dst.set<CodecConfiguration::CodecSpecific::aacConfig>(
+ src.get<CodecConfiguration::CodecSpecific::aacConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::ldacConfig:
+ dst.set<CodecConfiguration::CodecSpecific::ldacConfig>(
+ src.get<CodecConfiguration::CodecSpecific::ldacConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::aptxConfig:
+ dst.set<CodecConfiguration::CodecSpecific::aptxConfig>(
+ src.get<CodecConfiguration::CodecSpecific::aptxConfig>());
+ break;
+ case CodecConfiguration::CodecSpecific::lc3Config:
+ dst.set<CodecConfiguration::CodecSpecific::lc3Config>(
+ src.get<CodecConfiguration::CodecSpecific::lc3Config>());
+ break;
+ case CodecConfiguration::CodecSpecific::aptxAdaptiveConfig:
+ dst.set<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>(
+ src.get<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>());
+ break;
+ default:
+ break;
+ }
+}
+
+class BluetoothAudioPort : public BnBluetoothAudioPort {
+ public:
+ BluetoothAudioPort() {}
+
+ ndk::ScopedAStatus startStream() { return ScopedAStatus::ok(); }
+
+ ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }
+
+ ndk::ScopedAStatus stopStream() { return ScopedAStatus::ok(); }
+
+ ndk::ScopedAStatus getPresentationPosition(PresentationPosition*) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata&) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata&) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus setLatencyMode(const LatencyMode) {
+ return ScopedAStatus::ok();
+ }
+
+ ndk::ScopedAStatus setCodecType(const CodecType) {
+ return ScopedAStatus::ok();
+ }
+
+ protected:
+ virtual ~BluetoothAudioPort() = default;
+};
+
+class BluetoothAudioProviderFactoryAidl
+ : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ provider_factory_ = IBluetoothAudioProviderFactory::fromBinder(
+ SpAIBinder(AServiceManager_getService(GetParam().c_str())));
+ audio_provider_ = nullptr;
+ ASSERT_NE(provider_factory_, nullptr);
+ }
+
+ virtual void TearDown() override { provider_factory_ = nullptr; }
+
+ void GetProviderCapabilitiesHelper(const SessionType& session_type) {
+ temp_provider_capabilities_.clear();
+ auto aidl_retval = provider_factory_->getProviderCapabilities(
+ session_type, &temp_provider_capabilities_);
+ // AIDL calls should not be failed and callback has to be executed
+ ASSERT_TRUE(aidl_retval.isOk());
+ switch (session_type) {
+ case SessionType::UNKNOWN: {
+ ASSERT_TRUE(temp_provider_capabilities_.empty());
+ } break;
+ case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+ case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
+ case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH: {
+ // All software paths are mandatory and must have exact 1
+ // "PcmParameters"
+ ASSERT_EQ(temp_provider_capabilities_.size(), 1);
+ ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
+ AudioCapabilities::pcmCapabilities);
+ } break;
+ case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
+ std::unordered_set<CodecType> codec_types;
+ // empty capability means offload is unsupported
+ for (auto& audio_capability : temp_provider_capabilities_) {
+ ASSERT_EQ(audio_capability.getTag(),
+ AudioCapabilities::a2dpCapabilities);
+ const auto& codec_capabilities =
+ audio_capability.get<AudioCapabilities::a2dpCapabilities>();
+ // Every codec can present once at most
+ ASSERT_EQ(codec_types.count(codec_capabilities.codecType), 0);
+ switch (codec_capabilities.codecType) {
+ case CodecType::SBC:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::sbcCapabilities);
+ break;
+ case CodecType::AAC:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::aacCapabilities);
+ break;
+ case CodecType::APTX:
+ case CodecType::APTX_HD:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::aptxCapabilities);
+ break;
+ case CodecType::LDAC:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::ldacCapabilities);
+ break;
+ case CodecType::LC3:
+ ASSERT_EQ(codec_capabilities.capabilities.getTag(),
+ CodecCapabilities::Capabilities::lc3Capabilities);
+ break;
+ case CodecType::APTX_ADAPTIVE:
+ case CodecType::VENDOR:
+ case CodecType::UNKNOWN:
+ break;
+ }
+ codec_types.insert(codec_capabilities.codecType);
+ }
+ } break;
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+ case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+ case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
+ ASSERT_FALSE(temp_provider_capabilities_.empty());
+ for (auto audio_capability : temp_provider_capabilities_) {
+ ASSERT_EQ(audio_capability.getTag(),
+ AudioCapabilities::leAudioCapabilities);
+ }
+ } break;
+ }
+ }
+
+ /***
+ * This helps to open the specified provider and check the openProvider()
+ * has corruct return values. BUT, to keep it simple, it does not consider
+ * the capability, and please do so at the SetUp of each session's test.
+ ***/
+ void OpenProviderHelper(const SessionType& session_type) {
+ auto aidl_retval =
+ provider_factory_->openProvider(session_type, &audio_provider_);
+ if (aidl_retval.isOk()) {
+ ASSERT_NE(session_type, SessionType::UNKNOWN);
+ ASSERT_NE(audio_provider_, nullptr);
+ audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
+ } else {
+ // Hardware offloading is optional
+ ASSERT_TRUE(
+ session_type == SessionType::UNKNOWN ||
+ session_type ==
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ session_type ==
+ SessionType::
+ LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_EQ(audio_provider_, nullptr);
+ }
+ }
+
+ bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
+ if (temp_provider_capabilities_.size() != 1 ||
+ temp_provider_capabilities_[0].getTag() !=
+ AudioCapabilities::pcmCapabilities) {
+ return false;
+ }
+ auto pcm_capability = temp_provider_capabilities_[0]
+ .get<AudioCapabilities::pcmCapabilities>();
+ return (contained_in_vector(pcm_capability.channelMode,
+ pcm_config.channelMode) &&
+ contained_in_vector(pcm_capability.sampleRateHz,
+ pcm_config.sampleRateHz) &&
+ contained_in_vector(pcm_capability.bitsPerSample,
+ pcm_config.bitsPerSample));
+ }
+
+ std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
+ std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
+ std::shared_ptr<IBluetoothAudioPort> audio_port_;
+ std::vector<AudioCapabilities> temp_provider_capabilities_;
+
+ static constexpr SessionType kSessionTypes[] = {
+ SessionType::UNKNOWN,
+ SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+ };
+};
+
+/**
+ * Test whether we can get the FactoryService from HIDL
+ */
+TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
+
+/**
+ * Test whether we can open a provider for each provider returned by
+ * getProviderCapabilities() with non-empty capabalities
+ */
+TEST_P(BluetoothAudioProviderFactoryAidl,
+ OpenProviderAndCheckCapabilitiesBySession) {
+ for (auto session_type : kSessionTypes) {
+ GetProviderCapabilitiesHelper(session_type);
+ OpenProviderHelper(session_type);
+ // We must be able to open a provider if its getProviderCapabilities()
+ // returns non-empty list.
+ EXPECT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+}
+
+/**
+ * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderA2dpSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareAidl, OpenA2dpSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_P(BluetoothAudioProviderA2dpSoftwareAidl,
+ StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : a2dp_sample_rates) {
+ for (auto bits_per_sample : a2dp_bits_per_samples) {
+ for (auto channel_mode : a2dp_channel_modes) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ };
+ bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
+ */
+class BluetoothAudioProviderA2dpHardwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+
+ void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
+ temp_codec_capabilities_ = nullptr;
+ for (auto& codec_capability : temp_provider_capabilities_) {
+ auto& a2dp_capabilities =
+ codec_capability.get<AudioCapabilities::a2dpCapabilities>();
+ if (a2dp_capabilities.codecType != codec_type) {
+ continue;
+ }
+ temp_codec_capabilities_ = &a2dp_capabilities;
+ }
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetSbcCodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> sbc_codec_specifics;
+ if (!supported) {
+ SbcConfiguration sbc_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ sbc_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(sbc_config));
+ return sbc_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::SBC);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::SBC) {
+ return sbc_codec_specifics;
+ }
+ // parse the capability
+ auto& sbc_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::sbcCapabilities>();
+ if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
+ return sbc_codec_specifics;
+ }
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int32_t sample_rate : sbc_capability.sampleRateHz) {
+ for (int8_t block_length : sbc_capability.blockLength) {
+ for (int8_t num_subbands : sbc_capability.numSubbands) {
+ for (int8_t bits_per_sample : sbc_capability.bitsPerSample) {
+ for (auto channel_mode : sbc_capability.channelMode) {
+ for (auto alloc_method : sbc_capability.allocMethod) {
+ SbcConfiguration sbc_data = {
+ .sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .blockLength = block_length,
+ .numSubbands = num_subbands,
+ .allocMethod = alloc_method,
+ .bitsPerSample = bits_per_sample,
+ .minBitpool = sbc_capability.minBitpool,
+ .maxBitpool = sbc_capability.maxBitpool};
+ sbc_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(sbc_data));
+ }
+ }
+ }
+ }
+ }
+ }
+ return sbc_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetAacCodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> aac_codec_specifics;
+ if (!supported) {
+ AacConfiguration aac_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ aac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aac_config));
+ return aac_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::AAC);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::AAC) {
+ return aac_codec_specifics;
+ }
+ // parse the capability
+ auto& aac_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::aacCapabilities>();
+
+ std::vector<bool> variable_bit_rate_enableds = {false};
+ if (aac_capability.variableBitRateSupported) {
+ variable_bit_rate_enableds.push_back(true);
+ }
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (auto object_type : aac_capability.objectType) {
+ for (int32_t sample_rate : aac_capability.sampleRateHz) {
+ for (auto channel_mode : aac_capability.channelMode) {
+ for (int8_t bits_per_sample : aac_capability.bitsPerSample) {
+ for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
+ AacConfiguration aac_data{
+ .objectType = object_type,
+ .sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .variableBitRateEnabled = variable_bit_rate_enabled,
+ .bitsPerSample = bits_per_sample};
+ aac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aac_data));
+ }
+ }
+ }
+ }
+ }
+ return aac_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetLdacCodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> ldac_codec_specifics;
+ if (!supported) {
+ LdacConfiguration ldac_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ ldac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(ldac_config));
+ return ldac_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::LDAC);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::LDAC) {
+ return ldac_codec_specifics;
+ }
+ // parse the capability
+ auto& ldac_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::ldacCapabilities>();
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int32_t sample_rate : ldac_capability.sampleRateHz) {
+ for (int8_t bits_per_sample : ldac_capability.bitsPerSample) {
+ for (auto channel_mode : ldac_capability.channelMode) {
+ for (auto quality_index : ldac_capability.qualityIndex) {
+ LdacConfiguration ldac_data{.sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .qualityIndex = quality_index,
+ .bitsPerSample = bits_per_sample};
+ ldac_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(ldac_data));
+ }
+ }
+ }
+ }
+ return ldac_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetAptxCodecSpecificSupportedList(bool is_hd, bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> aptx_codec_specifics;
+ if (!supported) {
+ AptxConfiguration aptx_config{.sampleRateHz = 0, .bitsPerSample = 0};
+ aptx_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aptx_config));
+ return aptx_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(
+ (is_hd ? CodecType::APTX_HD : CodecType::APTX));
+ if (temp_codec_capabilities_ == nullptr) {
+ return aptx_codec_specifics;
+ }
+ if ((is_hd && temp_codec_capabilities_->codecType != CodecType::APTX_HD) ||
+ (!is_hd && temp_codec_capabilities_->codecType != CodecType::APTX)) {
+ return aptx_codec_specifics;
+ }
+
+ // parse the capability
+ auto& aptx_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::aptxCapabilities>();
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int8_t bits_per_sample : aptx_capability.bitsPerSample) {
+ for (int32_t sample_rate : aptx_capability.sampleRateHz) {
+ for (auto channel_mode : aptx_capability.channelMode) {
+ AptxConfiguration aptx_data{.sampleRateHz = sample_rate,
+ .channelMode = channel_mode,
+ .bitsPerSample = bits_per_sample};
+ aptx_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(aptx_data));
+ }
+ }
+ }
+ return aptx_codec_specifics;
+ }
+
+ std::vector<CodecConfiguration::CodecSpecific>
+ GetLc3CodecSpecificSupportedList(bool supported) {
+ std::vector<CodecConfiguration::CodecSpecific> lc3_codec_specifics;
+ if (!supported) {
+ Lc3Configuration lc3_config{.samplingFrequencyHz = 0,
+ .frameDurationUs = 0};
+ lc3_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(lc3_config));
+ return lc3_codec_specifics;
+ }
+ GetA2dpOffloadCapabilityHelper(CodecType::LC3);
+ if (temp_codec_capabilities_ == nullptr ||
+ temp_codec_capabilities_->codecType != CodecType::LC3) {
+ return lc3_codec_specifics;
+ }
+ // parse the capability
+ auto& lc3_capability =
+ temp_codec_capabilities_->capabilities
+ .get<CodecCapabilities::Capabilities::lc3Capabilities>();
+
+ // combine those parameters into one list of
+ // CodecConfiguration::CodecSpecific
+ for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+ for (auto channel_mode : lc3_capability.channelMode) {
+ Lc3Configuration lc3_data{.samplingFrequencyHz = samplingFrequencyHz,
+ .channelMode = channel_mode,
+ .frameDurationUs = frameDurationUs};
+ lc3_codec_specifics.push_back(
+ CodecConfiguration::CodecSpecific(lc3_data));
+ }
+ }
+ }
+ return lc3_codec_specifics;
+ }
+
+ // temp storage saves the specified codec capability by
+ // GetOffloadCodecCapabilityHelper()
+ CodecCapabilities* temp_codec_capabilities_;
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl, OpenA2dpHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpSbcHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::SBC,
+ .encodedAudioBitrate = 328000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : sbc_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpAacHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::AAC,
+ .encodedAudioBitrate = 320000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : aac_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpLdacHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::LDAC,
+ .encodedAudioBitrate = 990000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : ldac_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * LDAC hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpLc3HardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = CodecType::LC3,
+ .encodedAudioBitrate = 990000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true);
+
+ for (auto& codec_specific : lc3_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * AptX hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpAptxHardwareSession) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+
+ for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+ CodecConfiguration codec_config = {
+ .codecType = codec_type,
+ .encodedAudioBitrate =
+ (codec_type == CodecType::APTX ? 352000 : 576000),
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+
+ auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
+ (codec_type == CodecType::APTX_HD ? true : false), true);
+
+ for (auto& codec_specific : aptx_codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * an invalid codec config
+ */
+TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
+ StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
+ if (!IsOffloadSupported()) {
+ return;
+ }
+ ASSERT_NE(audio_provider_, nullptr);
+
+ std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
+ for (auto codec_type : a2dp_codec_types) {
+ switch (codec_type) {
+ case CodecType::SBC:
+ codec_specifics = GetSbcCodecSpecificSupportedList(false);
+ break;
+ case CodecType::AAC:
+ codec_specifics = GetAacCodecSpecificSupportedList(false);
+ break;
+ case CodecType::LDAC:
+ codec_specifics = GetLdacCodecSpecificSupportedList(false);
+ break;
+ case CodecType::APTX:
+ codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
+ break;
+ case CodecType::APTX_HD:
+ codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
+ break;
+ case CodecType::LC3:
+ codec_specifics = GetLc3CodecSpecificSupportedList(false);
+ continue;
+ case CodecType::APTX_ADAPTIVE:
+ case CodecType::VENDOR:
+ case CodecType::UNKNOWN:
+ codec_specifics.clear();
+ break;
+ }
+ if (codec_specifics.empty()) {
+ continue;
+ }
+
+ CodecConfiguration codec_config = {
+ .codecType = codec_type,
+ .encodedAudioBitrate = 328000,
+ .peerMtu = 1005,
+ .isScmstEnabled = false,
+ };
+ for (auto codec_specific : codec_specifics) {
+ copy_codec_specific(codec_config.config, codec_specific);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(codec_config), latency_modes,
+ &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+}
+
+/**
+ * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderHearingAidSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t hearing_aid_sample_rates_[] = {0, 16000, 24000};
+ static constexpr int8_t hearing_aid_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode hearing_aid_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
+ OpenHearingAidSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
+ StartAndEndHearingAidSessionWithPossiblePcmConfig) {
+ for (int32_t sample_rate : hearing_aid_sample_rates_) {
+ for (int8_t bits_per_sample : hearing_aid_bits_per_samples_) {
+ for (auto channel_mode : hearing_aid_channel_modes_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ };
+ bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t le_audio_output_sample_rates_[] = {
+ 0, 8000, 16000, 24000, 32000, 44100, 48000,
+ };
+ static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode le_audio_output_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr int32_t le_audio_output_data_interval_us_[] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+ OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+ StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : le_audio_output_sample_rates_) {
+ for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+ for (auto channel_mode : le_audio_output_channel_modes_) {
+ for (auto data_interval_us : le_audio_output_data_interval_us_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ .dataIntervalUs = data_interval_us,
+ };
+ bool is_codec_config_valid =
+ IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_SOFTWARE_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
+ OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t le_audio_input_sample_rates_[] = {
+ 0, 8000, 16000, 24000, 32000, 44100, 48000};
+ static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode le_audio_input_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr int32_t le_audio_input_data_interval_us_[] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
+ OpenLeAudioInputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
+ StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : le_audio_input_sample_rates_) {
+ for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
+ for (auto channel_mode : le_audio_input_channel_modes_) {
+ for (auto data_interval_us : le_audio_input_data_interval_us_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ .dataIntervalUs = data_interval_us,
+ };
+ bool is_codec_config_valid =
+ IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioOutputHardwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ bool IsOffloadOutputSupported() {
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ if (le_audio_capability.unicastEncodeCapability.codecType !=
+ CodecType::UNKNOWN)
+ return true;
+ }
+ return false;
+ }
+
+ std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
+ bool supported) {
+ std::vector<Lc3Configuration> le_audio_codec_configs;
+ if (!supported) {
+ Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+ le_audio_codec_configs.push_back(lc3_config);
+ return le_audio_codec_configs;
+ }
+
+ // There might be more than one LeAudioCodecCapabilitiesSetting
+ std::vector<Lc3Capabilities> lc3_capabilities;
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ auto& unicast_capability =
+ decoding ? le_audio_capability.unicastDecodeCapability
+ : le_audio_capability.unicastEncodeCapability;
+ if (unicast_capability.codecType != CodecType::LC3) {
+ continue;
+ }
+ auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
+ UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+ lc3_capabilities.push_back(lc3_capability);
+ }
+
+ // Combine those parameters into one list of LeAudioCodecConfiguration
+ // This seems horrible, but usually each Lc3Capability only contains a
+ // single Lc3Configuration, which means every array has a length of 1.
+ for (auto& lc3_capability : lc3_capabilities) {
+ for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+ for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+ Lc3Configuration lc3_config = {
+ .samplingFrequencyHz = samplingFrequencyHz,
+ .frameDurationUs = frameDurationUs,
+ .octetsPerFrame = octetsPerFrame,
+ };
+ le_audio_codec_configs.push_back(lc3_config);
+ }
+ }
+ }
+ }
+
+ return le_audio_codec_configs;
+ }
+
+ LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
+ if (!IsOffloadOutputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
+ if (!IsOffloadOutputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioInputHardwareAidl
+ : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ bool IsOffloadInputSupported() {
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ if (le_audio_capability.unicastDecodeCapability.codecType !=
+ CodecType::UNKNOWN)
+ return true;
+ }
+ return false;
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+ OpenLeAudioInputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+ StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
+ if (!IsOffloadInputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
+ * stopped with Unicast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
+ DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
+ if (!IsOffloadInputSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs =
+ GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
+ LeAudioConfiguration le_audio_config = {
+ .codecType = CodecType::LC3,
+ .peerDelayUs = 0,
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_config.leAudioCodecConfig
+ .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
+
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_config), latency_modes,
+ &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
+ ASSERT_NE(audio_provider_, nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ static constexpr int32_t le_audio_output_sample_rates_[] = {
+ 0, 8000, 16000, 24000, 32000, 44100, 48000,
+ };
+ static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
+ static constexpr ChannelMode le_audio_output_channel_modes_[] = {
+ ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+ static constexpr int32_t le_audio_output_data_interval_us_[] = {
+ 0 /* Invalid */, 10000 /* Valid 10ms */};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+ DISABLED_OpenLeAudioOutputSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+ DISABLED_StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
+ for (auto sample_rate : le_audio_output_sample_rates_) {
+ for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
+ for (auto channel_mode : le_audio_output_channel_modes_) {
+ for (auto data_interval_us : le_audio_output_data_interval_us_) {
+ PcmConfiguration pcm_config{
+ .sampleRateHz = sample_rate,
+ .bitsPerSample = bits_per_sample,
+ .channelMode = channel_mode,
+ .dataIntervalUs = data_interval_us,
+ };
+ bool is_codec_config_valid =
+ IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(pcm_config), latency_modes,
+ &mq_desc);
+ DataMQ data_mq(mq_desc);
+
+ EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
+ if (is_codec_config_valid) {
+ EXPECT_TRUE(data_mq.isValid());
+ }
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+ }
+ }
+ }
+}
+
+/**
+ * openProvider LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
+ : public BluetoothAudioProviderFactoryAidl {
+ public:
+ virtual void SetUp() override {
+ BluetoothAudioProviderFactoryAidl::SetUp();
+ GetProviderCapabilitiesHelper(
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ OpenProviderHelper(
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+ ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+ audio_provider_ != nullptr);
+ }
+
+ virtual void TearDown() override {
+ audio_port_ = nullptr;
+ audio_provider_ = nullptr;
+ BluetoothAudioProviderFactoryAidl::TearDown();
+ }
+
+ bool IsBroadcastOffloadSupported() {
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ if (le_audio_capability.broadcastCapability.codecType !=
+ CodecType::UNKNOWN)
+ return true;
+ }
+ return false;
+ }
+
+ std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
+ std::vector<Lc3Configuration> le_audio_codec_configs;
+ if (!supported) {
+ Lc3Configuration lc3_config{.samplingFrequencyHz = 0, .pcmBitDepth = 0};
+ le_audio_codec_configs.push_back(lc3_config);
+ return le_audio_codec_configs;
+ }
+
+ // There might be more than one LeAudioCodecCapabilitiesSetting
+ std::vector<Lc3Capabilities> lc3_capabilities;
+ for (auto& capability : temp_provider_capabilities_) {
+ if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
+ continue;
+ }
+ auto& le_audio_capability =
+ capability.get<AudioCapabilities::leAudioCapabilities>();
+ auto& broadcast_capability = le_audio_capability.broadcastCapability;
+ if (broadcast_capability.codecType != CodecType::LC3) {
+ continue;
+ }
+ auto& lc3_capability = broadcast_capability.leAudioCodecCapabilities.get<
+ BroadcastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
+ for (int idx = 0; idx < lc3_capability->size(); idx++)
+ lc3_capabilities.push_back(*lc3_capability->at(idx));
+ }
+
+ // Combine those parameters into one list of LeAudioCodecConfiguration
+ // This seems horrible, but usually each Lc3Capability only contains a
+ // single Lc3Configuration, which means every array has a length of 1.
+ for (auto& lc3_capability : lc3_capabilities) {
+ for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
+ for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
+ for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
+ Lc3Configuration lc3_config = {
+ .samplingFrequencyHz = samplingFrequencyHz,
+ .frameDurationUs = frameDurationUs,
+ .octetsPerFrame = octetsPerFrame,
+ };
+ le_audio_codec_configs.push_back(lc3_config);
+ }
+ }
+ }
+ }
+
+ return le_audio_codec_configs;
+ }
+
+ LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ OpenLeAudioOutputHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with broadcast hardware encoding config
+ */
+TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
+ if (!IsBroadcastOffloadSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
+ LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+ .codecType = CodecType::LC3,
+ .streamMap = {},
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_broadcast_config.streamMap[0]
+ .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+ lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_broadcast_config),
+ latency_modes, &mq_desc);
+
+ ASSERT_TRUE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+/**
+ * Test whether each provider of type
+ * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
+ * started and stopped with Broadcast hardware encoding config
+ *
+ * Disabled since offload codec checking is not ready
+ */
+TEST_P(
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
+ if (!IsBroadcastOffloadSupported()) {
+ return;
+ }
+
+ auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
+ LeAudioBroadcastConfiguration le_audio_broadcast_config = {
+ .codecType = CodecType::LC3,
+ .streamMap = {},
+ };
+
+ for (auto& lc3_config : lc3_codec_configs) {
+ le_audio_broadcast_config.streamMap[0]
+ .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
+ lc3_config);
+ DataMQDesc mq_desc;
+ auto aidl_retval = audio_provider_->startSession(
+ audio_port_, AudioConfiguration(le_audio_broadcast_config),
+ latency_modes, &mq_desc);
+
+ // AIDL call should fail on invalid codec
+ ASSERT_FALSE(aidl_retval.isOk());
+ EXPECT_TRUE(audio_provider_->endSession().isOk());
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderFactoryAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderA2dpHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderHearingAidSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderHearingAidSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioOutputSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioOutputSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioInputSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioInputSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioOutputHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioOutputHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioInputHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioInputHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
+INSTANTIATE_TEST_SUITE_P(PerInstance,
+ BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(
+ IBluetoothAudioProviderFactory::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index a6fd798..8fd1ab5 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -307,7 +307,9 @@
if (session_type !=
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type !=
- SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
return false;
}
return true;
@@ -451,7 +453,9 @@
if (session_type !=
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type !=
- SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
+ session_type !=
+ SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
return std::vector<LeAudioCodecCapabilitiesSetting>(0);
}
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index b90a656..7187828 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -545,21 +545,6 @@
}
}
-void BluetoothAudioSession::SetCodecType(CodecType codec_type) {
- std::lock_guard<std::recursive_mutex> guard(mutex_);
- if (!IsSessionReady()) {
- LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
- << " has NO session";
- return;
- }
-
- auto hal_retval = stack_iface_->setCodecType(codec_type);
- if (!hal_retval.isOk()) {
- LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
- << toString(session_type_) << " failed";
- }
-}
-
bool BluetoothAudioSession::IsAidlAvailable() {
if (is_aidl_checked) return is_aidl_available;
is_aidl_available =
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
index 7725331..6e390cc 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -182,7 +182,6 @@
void UpdateSourceMetadata(const struct source_metadata& source_metadata);
void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
void SetLatencyMode(LatencyMode latency_mode);
- void SetCodecType(CodecType codec_type);
// The control function writes stream to FMQ
size_t OutWritePcmData(const void* buffer, size_t bytes);
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
index cb6ff4b..f229165 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
@@ -25,7 +25,8 @@
namespace aidl::android::hardware::neuralnetworks::utils {
-::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(const std::string& name);
+::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(
+ const std::string& name, ::android::nn::Version::Level maxFeatureLevelAllowed);
} // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index e48593c..24fbb53 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -55,11 +55,12 @@
} // namespace
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
+nn::GeneralResult<nn::SharedDevice> getDevice(
+ const std::string& instanceName, ::android::nn::Version::Level maxFeatureLevelAllowed) {
auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
hal::utils::ResilientDevice::Factory makeDevice =
- [instanceName,
- name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+ [instanceName, name = std::move(fullName),
+ maxFeatureLevelAllowed](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
std::add_pointer_t<AIBinder*(const char*)> getService;
if (blocking) {
if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
@@ -79,7 +80,8 @@
<< " returned nullptr";
}
ABinderProcess_startThreadPool();
- const auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
+ auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
+ featureLevel.level = std::min(featureLevel.level, maxFeatureLevelAllowed);
return Device::create(instanceName, std::move(service), featureLevel);
};
diff --git a/neuralnetworks/utils/service/include/nnapi/hal/Service.h b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
index 2fd5237..e8b9c10 100644
--- a/neuralnetworks/utils/service/include/nnapi/hal/Service.h
+++ b/neuralnetworks/utils/service/include/nnapi/hal/Service.h
@@ -29,7 +29,18 @@
bool isDeviceUpdatable = false;
};
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers);
+/**
+ * @brief Get the NNAPI sAIDL and HIDL services declared in the VINTF.
+ *
+ * @pre maxFeatureLevelAllowed >= Version::Level::FEATURE_LEVEL_5
+ *
+ * @param includeUpdatableDrivers Allow updatable drivers to be used.
+ * @param maxFeatureLevelAllowed Maximum version of driver allowed to be used. Any driver version
+ * exceeding this must be clamped to `maxFeatureLevelAllowed`.
+ * @return A list of devices and whether each device is updatable or not.
+ */
+std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers,
+ nn::Version::Level maxFeatureLevelAllowed);
} // namespace android::hardware::neuralnetworks::service
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index 2286288..e0d5f82 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -74,7 +74,7 @@
void getAidlDevices(std::vector<SharedDeviceAndUpdatability>* devices,
std::unordered_set<std::string>* registeredDevices,
- bool includeUpdatableDrivers) {
+ bool includeUpdatableDrivers, nn::Version::Level maxFeatureLevelAllowed) {
CHECK(devices != nullptr);
CHECK(registeredDevices != nullptr);
@@ -100,7 +100,7 @@
continue;
}
if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
- auto maybeDevice = aidl_hal::utils::getDevice(name);
+ auto maybeDevice = aidl_hal::utils::getDevice(name, maxFeatureLevelAllowed);
if (maybeDevice.has_value()) {
auto device = std::move(maybeDevice).value();
CHECK(device != nullptr);
@@ -116,11 +116,14 @@
} // namespace
-std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers) {
+std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers,
+ nn::Version::Level maxFeatureLevelAllowed) {
std::vector<SharedDeviceAndUpdatability> devices;
std::unordered_set<std::string> registeredDevices;
- getAidlDevices(&devices, ®isteredDevices, includeUpdatableDrivers);
+ CHECK_GE(maxFeatureLevelAllowed, nn::Version::Level::FEATURE_LEVEL_5);
+
+ getAidlDevices(&devices, ®isteredDevices, includeUpdatableDrivers, maxFeatureLevelAllowed);
getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
®isteredDevices);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index fe10587..5224624 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -16,8 +16,37 @@
#include <sap_hidl_hal_utils.h>
+bool isServiceValidForDeviceConfiguration(hidl_string& serviceName) {
+ if (isSsSsEnabled()) {
+ // Device is configured as SSSS.
+ if (serviceName != SAP_SERVICE_SLOT1_NAME) {
+ LOG(DEBUG) << "Not valid for SSSS device.";
+ return false;
+ }
+ } else if (isDsDsEnabled()) {
+ // Device is configured as DSDS.
+ if (serviceName != SAP_SERVICE_SLOT1_NAME && serviceName != SAP_SERVICE_SLOT2_NAME) {
+ LOG(DEBUG) << "Not valid for DSDS device.";
+ return false;
+ }
+ } else if (isTsTsEnabled()) {
+ // Device is configured as TSTS.
+ if (serviceName != SAP_SERVICE_SLOT1_NAME && serviceName != SAP_SERVICE_SLOT2_NAME &&
+ serviceName != SAP_SERVICE_SLOT3_NAME) {
+ LOG(DEBUG) << "Not valid for TSTS device.";
+ return false;
+ }
+ }
+ return true;
+}
+
void SapHidlTest::SetUp() {
- sap = ISap::getService(GetParam());
+ hidl_string serviceName = GetParam();
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ LOG(DEBUG) << "Skipped the test due to device configuration.";
+ GTEST_SKIP();
+ }
+ sap = ISap::getService(serviceName);
ASSERT_NE(sap, nullptr);
sapCb = new SapCallback(*this);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_utils.h b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
index 2fc9ae3..8e86591 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
@@ -36,7 +36,15 @@
using ::android::sp;
#define TIMEOUT_PERIOD 40
-#define SAP_SERVICE_NAME "slot1"
+
+// HAL instance name for SIM slot 1 or single SIM device
+#define SAP_SERVICE_SLOT1_NAME "slot1"
+
+// HAL instance name for SIM slot 2 on dual SIM device
+#define SAP_SERVICE_SLOT2_NAME "slot2"
+
+// HAL instance name for SIM slot 3 on triple SIM device
+#define SAP_SERVICE_SLOT3_NAME "slot3"
class SapHidlTest;
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
index eec28b1..249ee63 100644
--- a/radio/aidl/vts/radio_voice_test.cpp
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -943,3 +943,37 @@
}
LOG(DEBUG) << "cancelPendingUssd finished";
}
+
+/*
+ * Test IRadioVoice.isVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, isVoNrEnabled) {
+ LOG(DEBUG) << "isVoNrEnabled";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->isVoNrEnabled(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ LOG(DEBUG) << "isVoNrEnabled finished";
+}
+
+/*
+ * Test IRadioVoice.setVoNrEnabled() for the response returned.
+ */
+TEST_P(RadioVoiceTest, setVoNrEnabled) {
+ LOG(DEBUG) << "setVoNrEnabled";
+ serial = GetRandomSerialNumber();
+
+ radio_voice->setVoNrEnabled(serial, true);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_voice->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_voice->rspInfo.serial);
+
+ ASSERT_TRUE(CheckAnyOfErrors(radioRsp_voice->rspInfo.error,
+ {RadioError::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ LOG(DEBUG) << "setVoNrEnabled finished";
+}
diff --git a/security/dice/aidl/Android.bp b/security/dice/aidl/Android.bp
index 01bc91e..8c31e26 100644
--- a/security/dice/aidl/Android.bp
+++ b/security/dice/aidl/Android.bp
@@ -38,6 +38,10 @@
enabled: true,
},
apps_enabled: false,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.compos",
+ ],
},
rust: {
enabled: true,
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index 727c6b7..8a26b3c 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -219,18 +219,22 @@
AttestationKey attest_key;
vector<KeyCharacteristics> attest_key_characteristics;
vector<Certificate> attest_key_cert_chain;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaKey(2048, 65537)
- .AttestKey()
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- {} /* attestation signing key */, &attest_key.keyBlob,
- &attest_key_characteristics, &attest_key_cert_chain));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
EXPECT_GT(attest_key_cert_chain.size(), 1);
verify_subject_and_serial(attest_key_cert_chain[0], serial_int, subject, false);
@@ -319,18 +323,22 @@
attest_key_opt = attest_key;
}
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaKey(2048, 65537)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -392,18 +400,22 @@
attest_key_opt = attest_key;
}
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaKey(EcCurve::P_256)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
@@ -484,34 +496,37 @@
attest_key.keyBlob = key_blob_list[i - 1];
attest_key_opt = attest_key;
}
-
+ ErrorCode result;
if ((i & 0x1) == 1) {
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaKey(EcCurve::P_256)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
} else {
- EXPECT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaKey(2048, 65537)
- .AttestKey()
- .AttestationChallenge("foo")
- .AttestationApplicationId("bar")
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
- &cert_chain_list[i]));
+ result = GenerateKey(AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ attest_key_opt, &key_blob_list[i], &attested_key_characteristics,
+ &cert_chain_list[i]);
}
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 146a527..ff4036c 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1228,6 +1228,14 @@
}
}
+vector<uint64_t> KeyMintAidlTestBase::ValidExponents() {
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ return {65537};
+ } else {
+ return {3, 65537};
+ }
+}
+
vector<Digest> KeyMintAidlTestBase::ValidDigests(bool withNone, bool withMD5) {
switch (SecLevel()) {
case SecurityLevel::SOFTWARE:
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 27cb99c..6fb5bf5 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -253,7 +253,10 @@
.SetDefaultValidity();
tagModifier(&rsaBuilder);
errorCode = GenerateKey(rsaBuilder, &rsaKeyData.blob, &rsaKeyData.characteristics);
- EXPECT_EQ(expectedReturn, errorCode);
+ if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+ ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+ EXPECT_EQ(expectedReturn, errorCode);
+ }
/* ECDSA */
KeyData ecdsaKeyData;
@@ -265,7 +268,10 @@
.SetDefaultValidity();
tagModifier(&ecdsaBuilder);
errorCode = GenerateKey(ecdsaBuilder, &ecdsaKeyData.blob, &ecdsaKeyData.characteristics);
- EXPECT_EQ(expectedReturn, errorCode);
+ if (!(SecLevel() == SecurityLevel::STRONGBOX &&
+ ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED == errorCode)) {
+ EXPECT_EQ(expectedReturn, errorCode);
+ }
return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
}
bool IsSecure() const { return securityLevel_ != SecurityLevel::SOFTWARE; }
@@ -282,6 +288,7 @@
vector<EcCurve> InvalidCurves();
vector<Digest> ValidDigests(bool withNone, bool withMD5);
+ vector<uint64_t> ValidExponents();
static vector<string> build_params() {
auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 62f22bb..4a32c2f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1036,18 +1036,21 @@
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_size, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1169,17 +1172,21 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaEncryptionKey(key_size, 65537)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaEncryptionKey(key_size, 65537)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
AuthorizationSet auths;
@@ -1281,15 +1288,19 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
}
/*
@@ -1399,19 +1410,23 @@
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(key_size, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(key_size, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
@@ -1601,17 +1616,21 @@
for (auto curve : ValidCurves()) {
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK,
- GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(curve)
- .Digest(Digest::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
- .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(curve)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -1745,6 +1764,10 @@
// Tag not required to be supported by all KeyMint implementations.
continue;
}
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
ASSERT_EQ(result, ErrorCode::OK);
ASSERT_GT(key_blob.size(), 0U);
@@ -1840,6 +1863,10 @@
AuthorizationSetBuilder builder = base_builder;
builder.push_back(tag);
auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
if (result == ErrorCode::CANNOT_ATTEST_IDS) {
// Device ID attestation is optional; KeyMint may not support it at all.
continue;
@@ -1997,6 +2024,10 @@
.Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
.SetDefaultValidity(),
&key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
ASSERT_EQ(result, ErrorCode::OK);
ASSERT_GT(key_blob.size(), 0U);
@@ -2076,13 +2107,17 @@
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
- GenerateKey(AuthorizationSetBuilder()
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::NONE)
- .AttestationChallenge(challenge)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING, result);
}
/*
@@ -2139,14 +2174,19 @@
const string app_id(length, 'a');
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .EcdsaSigningKey(EcCurve::P_256)
- .Digest(Digest::NONE)
- .AttestationChallenge(challenge)
- .AttestationApplicationId(app_id)
- .SetDefaultValidity(),
- &key_blob, &key_characteristics));
+ auto result = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .SetDefaultValidity(),
+ &key_blob, &key_characteristics);
+ // Strongbox may not support factory provisioned attestation key.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ if (result == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED) return;
+ }
+ ASSERT_EQ(ErrorCode::OK, result);
ASSERT_GT(key_blob.size(), 0U);
CheckBaseParams(key_characteristics);
CheckCharacteristics(key_blob, key_characteristics);
@@ -4646,7 +4686,7 @@
* Verifies that raw RSA decryption works.
*/
TEST_P(EncryptionOperationsTest, RsaNoPaddingSuccess) {
- for (uint64_t exponent : {3, 65537}) {
+ for (uint64_t exponent : ValidExponents()) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaEncryptionKey(2048, exponent)
@@ -7209,7 +7249,7 @@
size_t i;
for (i = 0; i < max_operations; i++) {
- result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+ result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]);
if (ErrorCode::OK != result) {
break;
}
@@ -7217,12 +7257,12 @@
EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result);
// Try again just in case there's a weird overflow bug
EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
- Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+ Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
for (size_t j = 0; j < i; j++) {
EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
<< "Aboort failed for i = " << j << std::endl;
}
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
AbortIfNeeded();
}
@@ -7611,14 +7651,23 @@
});
for (const auto& keyData : {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData}) {
+ // Strongbox may not support factory attestation. Key creation might fail with
+ // ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED
+ if (SecLevel() == SecurityLevel::STRONGBOX && keyData.blob.size() == 0U) {
+ continue;
+ }
ASSERT_GT(keyData.blob.size(), 0U);
AuthorizationSet crypto_params = SecLevelAuthorizations(keyData.characteristics);
EXPECT_TRUE(crypto_params.Contains(TAG_EARLY_BOOT_ONLY)) << crypto_params;
}
CheckedDeleteKey(&aesKeyData.blob);
CheckedDeleteKey(&hmacKeyData.blob);
- CheckedDeleteKey(&rsaKeyData.blob);
- CheckedDeleteKey(&ecdsaKeyData.blob);
+ if (rsaKeyData.blob.size() != 0U) {
+ CheckedDeleteKey(&rsaKeyData.blob);
+ }
+ if (ecdsaKeyData.blob.size() != 0U) {
+ CheckedDeleteKey(&ecdsaKeyData.blob);
+ }
}
/*
diff --git a/tv/Android.mk b/tv/Android.mk
new file mode 100644
index 0000000..d78614a
--- /dev/null
+++ b/tv/Android.mk
@@ -0,0 +1,2 @@
+$(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_0.xml))
+$(eval $(call declare-1p-copy-files,hardware/interfaces/tv,tuner_vts_config_1_1.xml))
diff --git a/update-base-files.sh b/update-base-files.sh
index d01847d..bf7f6e4 100755
--- a/update-base-files.sh
+++ b/update-base-files.sh
@@ -45,8 +45,11 @@
-o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio_common-base.h \
android.hardware.audio.common@7.0
hidl-gen $options \
- -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base.h \
+ -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base-v7.0.h \
android.hardware.audio@7.0
hidl-gen $options \
+ -o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio-base-v7.1.h \
+ android.hardware.audio@7.1
+hidl-gen $options \
-o $ANDROID_BUILD_TOP/system/media/audio/include/system/audio_effect-base.h \
android.hardware.audio.effect@7.0
diff --git a/vibrator/aidl/OWNERS b/vibrator/aidl/OWNERS
index ae10db6..3982c7b 100644
--- a/vibrator/aidl/OWNERS
+++ b/vibrator/aidl/OWNERS
@@ -1,4 +1,4 @@
# Bug component: 345036
include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
chasewu@google.com
-leungv@google.com
+taikuo@google.com