Merge "Add VTS test for VoNR apis on IRadio aidl"
diff --git a/audio/7.1/Android.bp b/audio/7.1/Android.bp
index 52980e2..cede72a 100644
--- a/audio/7.1/Android.bp
+++ b/audio/7.1/Android.bp
@@ -17,7 +17,6 @@
"IDevice.hal",
"IDevicesFactory.hal",
"IPrimaryDevice.hal",
- "IStreamIn.hal",
"IStreamOut.hal",
"IStreamOutLatencyModeCallback.hal",
],
diff --git a/audio/7.1/IDevice.hal b/audio/7.1/IDevice.hal
index 373d17f..c158e7e 100644
--- a/audio/7.1/IDevice.hal
+++ b/audio/7.1/IDevice.hal
@@ -20,7 +20,6 @@
import @7.0::AudioInOutFlag;
import @7.0::IDevice;
import @7.0::Result;
-import IStreamIn;
import IStreamOut;
interface IDevice extends @7.0::IDevice {
@@ -56,33 +55,14 @@
AudioConfig suggestedConfig);
/**
- * This method creates and opens the audio hardware input stream.
- * If the stream can not be opened with the proposed audio config,
- * HAL must provide suggested values for the audio config.
+ * Notifies the device module about the connection state of an input/output
+ * device attached to it. The devicePort identifies the device and may also
+ * provide extra information such as raw audio descriptors.
*
- * Note: INVALID_ARGUMENTS is returned both in the case when the
- * HAL can not use the provided config and in the case when
- * the value of any argument is invalid. In the latter case the
- * HAL must provide a default initialized suggested config.
- *
- * @param ioHandle handle assigned by AudioFlinger.
- * @param device device type and (if needed) address.
- * @param config stream configuration.
- * @param flags additional flags.
- * @param sinkMetadata Description of the audio that is suggested by the client.
- * May be used by implementations to configure processing effects.
+ * @param devicePort audio device port.
+ * @param connected whether the device is connected.
* @return retval operation completion status.
- * @return inStream in case of success, created input stream.
- * @return suggestedConfig in the case of rejection of the proposed config,
- * a config suggested by the HAL.
*/
- openInputStream_7_1(
- AudioIoHandle ioHandle,
- DeviceAddress device,
- AudioConfig config,
- vec<AudioInOutFlag> flags,
- SinkMetadata sinkMetadata) generates (
- Result retval,
- IStreamIn inStream,
- AudioConfig suggestedConfig);
+ setConnectedState_7_1(AudioPort devicePort, bool connected)
+ generates (Result retval);
};
diff --git a/audio/7.1/IStreamIn.hal b/audio/7.1/IStreamIn.hal
deleted file mode 100644
index abebe6a..0000000
--- a/audio/7.1/IStreamIn.hal
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-package android.hardware.audio@7.1;
-
-import @7.0::IStreamIn;
-
-interface IStreamIn extends @7.0::IStreamIn {
-};
diff --git a/audio/7.1/config/api/current.txt b/audio/7.1/config/api/current.txt
index 0a0eb02..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;
@@ -462,6 +467,7 @@
method @Nullable public String getName();
method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.AudioUsage> getPreferredUsage();
method @Nullable public java.util.List<android.audio.policy.configuration.V7_1.Profile> getProfile();
+ method @Nullable public long getRecommendedMuteDurationMs();
method @Nullable public android.audio.policy.configuration.V7_1.Role getRole();
method public void setFlags(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioInOutFlag>);
method public void setGains(@Nullable android.audio.policy.configuration.V7_1.Gains);
@@ -469,6 +475,7 @@
method public void setMaxOpenCount(@Nullable long);
method public void setName(@Nullable String);
method public void setPreferredUsage(@Nullable java.util.List<android.audio.policy.configuration.V7_1.AudioUsage>);
+ method public void setRecommendedMuteDurationMs(@Nullable long);
method public void setRole(@Nullable android.audio.policy.configuration.V7_1.Role);
}
diff --git a/audio/7.1/config/audio_policy_configuration.xsd b/audio/7.1/config/audio_policy_configuration.xsd
index defb506..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">
@@ -226,6 +228,7 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="recommendedMuteDurationMs" type="xs:unsignedInt"/>
</xs:complexType>
<xs:unique name="mixPortProfileUniqueness">
<xs:selector xpath="profile"/>
@@ -440,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" />
@@ -470,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">
@@ -741,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..3472af1 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -20,6 +20,7 @@
#include <string>
#include <vector>
+#include <android/binder_process.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <hidl/HidlTransportSupport.h>
@@ -52,6 +53,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);
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 86380a5..3536561 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -48,6 +48,8 @@
"libhidlbase",
"liblog",
"libmedia_helper",
+ "libmediautils_vendor",
+ "libmemunreachable",
"libutils",
"android.hardware.audio.common-util",
],
@@ -166,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/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 98a59b9..b954fcd 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -30,6 +30,8 @@
#include <algorithm>
#include <android/log.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
#include <HidlUtils.h>
@@ -346,16 +348,6 @@
_hidl_cb(result, streamOut, suggestedConfig);
return Void();
}
-
-Return<void> Device::openInputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
- const AudioConfig& config, const AudioInputFlags& flags,
- const SinkMetadata& sinkMetadata,
- openInputStream_7_1_cb _hidl_cb) {
- auto [result, streamIn, suggestedConfig] =
- openInputStreamImpl(ioHandle, device, config, flags, sinkMetadata);
- _hidl_cb(result, streamIn, suggestedConfig);
- return Void();
-}
#endif // V7.1
Return<bool> Device::supportsAudioPatches() {
@@ -501,9 +493,32 @@
}
#endif
-Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
- analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+ const int fd0 = fd->data[0];
+ bool dumpMem = false;
+ bool unreachableMemory = false;
+ for (const auto& option : options) {
+ if (option == "-m") {
+ dumpMem = true;
+ } else if (option == "--unreachable") {
+ unreachableMemory = true;
+ }
+ }
+
+ if (dumpMem) {
+ dprintf(fd0, "\nDumping memory:\n");
+ std::string s = dumpMemoryAddresses(100 /* limit */);
+ write(fd0, s.c_str(), s.size());
+ }
+ if (unreachableMemory) {
+ dprintf(fd0, "\nDumping unreachable memory:\n");
+ // TODO - should limit be an argument parameter?
+ std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+ write(fd0, s.c_str(), s.size());
+ }
+
+ analyzeStatus("dump", mDevice->dump(mDevice, fd0));
}
return Void();
}
@@ -591,6 +606,21 @@
#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+Return<Result> Device::setConnectedState_7_1(const AudioPort& devicePort, bool connected) {
+ if (version() >= AUDIO_DEVICE_API_VERSION_3_2 &&
+ mDevice->set_device_connected_state_v7 != nullptr) {
+ audio_port_v7 halPort;
+ if (status_t status = HidlUtils::audioPortToHal(devicePort, &halPort); status != NO_ERROR) {
+ return analyzeStatus("audioPortToHal", status);
+ }
+ return analyzeStatus("set_device_connected_state_v7",
+ mDevice->set_device_connected_state_v7(mDevice, &halPort, connected));
+ }
+ return Result::NOT_SUPPORTED;
+}
+#endif
+
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
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/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index 0aeb6b3..0696f97 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -123,10 +123,6 @@
const AudioConfig& config, const AudioOutputFlags& flags,
const SourceMetadata& sourceMetadata,
openOutputStream_7_1_cb _hidl_cb) override;
- Return<void> openInputStream_7_1(int32_t ioHandle, const DeviceAddress& device,
- const AudioConfig& config, const AudioInputFlags& flags,
- const SinkMetadata& sinkMetadata,
- openInputStream_7_1_cb _hidl_cb) override;
#endif
Return<bool> supportsAudioPatches() override;
@@ -163,6 +159,9 @@
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) override;
#endif
+#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
+ Return<Result> setConnectedState_7_1(const AudioPort& devicePort, bool connected) override;
+#endif
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Utility methods for extending interfaces.
diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h
index a6346e5..4627eec 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -17,7 +17,9 @@
#ifndef ANDROID_HARDWARE_AUDIO_STREAMIN_H
#define ANDROID_HARDWARE_AUDIO_STREAMIN_H
-#include PATH(android/hardware/audio/FILE_VERSION/IStreamIn.h)
+// clang-format off
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamIn.h)
+// clang-format on
#include "Device.h"
#include "Stream.h"
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/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
index a567cf9..83ca9eb 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h
@@ -15,9 +15,9 @@
*/
// clang-format off
-#include PATH(android/hardware/audio/FILE_VERSION/IStreamIn.h)
-#include PATH(android/hardware/audio/FILE_VERSION/IStreamOut.h)
+#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamIn.h)
#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h)
+#include PATH(android/hardware/audio/FILE_VERSION/IStreamOut.h)
#include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h)
// clang-format on
#include <hidl/HidlSupport.h>
diff --git a/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
index b750f56..d82d4ad 100644
--- a/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.1/AudioPrimaryHidlHalTest.cpp
@@ -16,3 +16,34 @@
// pull in all the <= 7.0 tests
#include "7.0/AudioPrimaryHidlHalTest.cpp"
+
+TEST_P(AudioHidlDeviceTest, SetConnectedState_7_1) {
+ doc::test("Check that the HAL can be notified of device connection and disconnection");
+ using AD = xsd::AudioDevice;
+ for (auto deviceType : {AD::AUDIO_DEVICE_OUT_HDMI, AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AD::AUDIO_DEVICE_IN_USB_HEADSET}) {
+ SCOPED_TRACE("device=" + toString(deviceType));
+ for (bool state : {true, false}) {
+ SCOPED_TRACE("state=" + ::testing::PrintToString(state));
+ DeviceAddress address = {};
+ address.deviceType = toString(deviceType);
+ if (deviceType == AD::AUDIO_DEVICE_IN_USB_HEADSET) {
+ address.address.alsa({0, 0});
+ }
+ AudioPort devicePort;
+ devicePort.ext.device(address);
+ auto ret = getDevice()->setConnectedState_7_1(devicePort, state);
+ ASSERT_TRUE(ret.isOk());
+ if (ret == Result::NOT_SUPPORTED) {
+ doc::partialTest("setConnectedState_7_1 is not supported");
+ break; // other deviceType might be supported
+ }
+ ASSERT_OK(ret);
+ }
+ }
+
+ // Because there is no way of knowing if the devices were connected before
+ // calling setConnectedState, there is no way to restore the HAL to its
+ // initial state. To workaround this, destroy the HAL at the end of this test.
+ ASSERT_TRUE(resetDevice());
+}
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/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 404532a..fa3ee7f 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -91,8 +91,9 @@
using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
using namespace ::android::hardware::audio::common::test::utility;
using namespace ::android::hardware::audio::CPP_VERSION;
-using ReadParameters = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadParameters;
-using ReadStatus = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadStatus;
+using ReadParameters =
+ ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadParameters;
+using ReadStatus = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadStatus;
using WriteCommand = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteCommand;
using WriteStatus = ::android::hardware::audio::CPP_VERSION::IStreamOut::WriteStatus;
#if MAJOR_VERSION >= 7
@@ -1089,7 +1090,7 @@
class StreamReader : public StreamWorker<StreamReader> {
public:
- using IStreamIn = ::android::hardware::audio::CPP_VERSION::IStreamIn;
+ using IStreamIn = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn;
StreamReader(IStreamIn* stream, size_t bufferSize)
: mStream(stream), mBufferSize(bufferSize), mData(mBufferSize) {}
@@ -1204,7 +1205,8 @@
EventFlag* mEfGroup = nullptr;
};
-class InputStreamTest : public OpenStreamTest<::android::hardware::audio::CPP_VERSION::IStreamIn> {
+class InputStreamTest
+ : public OpenStreamTest<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> {
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base
#if MAJOR_VERSION <= 6
@@ -1226,13 +1228,8 @@
auto flags = getInputFlags();
testOpen(
[&](AudioIoHandle handle, AudioConfig config, auto cb) {
-#if MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0)
return getDevice()->openInputStream(handle, address, config, flags,
initMetadata, cb);
-#elif MAJOR_VERSION == 7 && MINOR_VERSION == 1
- return getDevice()->openInputStream_7_1(handle, address, config, flags,
- initMetadata, cb);
-#endif
},
config);
}
@@ -1605,8 +1602,9 @@
"InputStream::setGain");
}
-static void testPrepareForReading(::android::hardware::audio::CPP_VERSION::IStreamIn* stream,
- uint32_t frameSize, uint32_t framesCount) {
+static void testPrepareForReading(
+ ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn* stream, uint32_t frameSize,
+ uint32_t framesCount) {
Result res;
// Ignore output parameters as the call should fail
ASSERT_OK(stream->prepareForReading(frameSize, framesCount,
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/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/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..4454cc3
--- /dev/null
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -0,0 +1,1660 @@
+/*
+ * 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};
+
+// 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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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), &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 967b6f3..7187828 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -426,8 +426,8 @@
for (auto& observer : observers_) {
uint16_t cookie = observer.first;
std::shared_ptr<PortStatusCallbacks> callback = observer.second;
- LOG(INFO) << __func__ << " - allowed="
- << allowed ? " allowed" : " disallowed";
+ LOG(INFO) << __func__
+ << " - allowed=" << (allowed ? " allowed" : " disallowed");
callback->low_latency_mode_allowed_cb_(cookie, allowed);
}
}
@@ -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 =
@@ -599,4 +584,4 @@
} // namespace bluetooth
} // namespace hardware
} // namespace android
-} // namespace aidl
\ No newline at end of file
+} // namespace aidl
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/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp
index 3f4b5bc..4190769 100644
--- a/health/utils/libhealthloop/HealthLoop.cpp
+++ b/health/utils/libhealthloop/HealthLoop.cpp
@@ -40,8 +40,6 @@
using namespace android;
using namespace std::chrono_literals;
-#define POWER_SUPPLY_SUBSYSTEM "power_supply"
-
namespace android {
namespace hardware {
namespace health {
@@ -143,7 +141,7 @@
cp = msg;
while (*cp) {
- if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
+ if (!strcmp(cp, "SUBSYSTEM=power_supply")) {
ScheduleBatteryUpdate();
break;
}
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/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/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