Define an extensible audio device description
The new way for describing audio devices which can be used
both in framework <-> framework and framework <-> HAL
interfaces and directly supports extensions by vendors.
The mapping is defined between the legacy audio_devices_t
and the new descriptions.
Bug: 188932434
Test: atest audio_aidl_conversion_tests
Change-Id: Ifef9fdb510e21765aa548a2877edb84cdf46ac75
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 8f3d996..fa78f43 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -412,10 +412,205 @@
namespace {
namespace detail {
+using AudioDevicePair = std::pair<audio_devices_t, media::AudioDeviceDescription>;
+using AudioDevicePairs = std::vector<AudioDevicePair>;
using AudioFormatPair = std::pair<audio_format_t, media::AudioFormatDescription>;
using AudioFormatPairs = std::vector<AudioFormatPair>;
}
+media::AudioDeviceDescription make_AudioDeviceDescription(media::AudioDeviceType type,
+ const std::string& connection = "") {
+ media::AudioDeviceDescription result;
+ result.type = type;
+ result.connection = connection;
+ return result;
+}
+
+void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
+ audio_devices_t inputType, audio_devices_t outputType,
+ media::AudioDeviceType inType, media::AudioDeviceType outType,
+ const std::string& connection = "") {
+ pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
+ pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
+}
+
+const detail::AudioDevicePairs& getAudioDevicePairs() {
+ static const detail::AudioDevicePairs pairs = []() {
+ detail::AudioDevicePairs pairs = {{
+ {
+ AUDIO_DEVICE_NONE, media::AudioDeviceDescription{}
+ },
+ {
+ AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_SPEAKER_EARPIECE)
+ },
+ {
+ AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_SPEAKER)
+ },
+ {
+ AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_HEADPHONE,
+ media::AudioDeviceDescription::CONNECTION_ANALOG())
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_BT_SCO())
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_CARKIT,
+ media::AudioDeviceDescription::CONNECTION_BT_SCO())
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_HEADPHONE,
+ media::AudioDeviceDescription::CONNECTION_BT_A2DP())
+ },
+ {
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_SPEAKER,
+ media::AudioDeviceDescription::CONNECTION_BT_A2DP())
+ },
+ {
+ AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_TELEPHONY_TX)
+ },
+ {
+ AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_LINE_AUX)
+ },
+ {
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_SPEAKER_SAFE)
+ },
+ {
+ AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_HEARING_AID,
+ media::AudioDeviceDescription::CONNECTION_WIRELESS())
+ },
+ {
+ AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_ECHO_CANCELLER)
+ },
+ {
+ AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
+ media::AudioDeviceType::OUT_SPEAKER,
+ media::AudioDeviceDescription::CONNECTION_BT_LE())
+ },
+ // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
+ {
+ AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_MICROPHONE)
+ },
+ {
+ AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_MICROPHONE_BACK)
+ },
+ {
+ AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_TELEPHONY_RX)
+ },
+ {
+ AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_TV_TUNER)
+ },
+ {
+ AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_LOOPBACK)
+ },
+ {
+ AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_BT_LE())
+ },
+ {
+ AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
+ media::AudioDeviceType::IN_ECHO_REFERENCE)
+ }
+ }};
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
+ media::AudioDeviceType::IN_DEFAULT, media::AudioDeviceType::OUT_DEFAULT);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+ media::AudioDeviceType::IN_HEADSET, media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_ANALOG());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+ media::AudioDeviceType::IN_HEADSET, media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_BT_SCO());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_HDMI());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ media::AudioDeviceType::IN_SUBMIX, media::AudioDeviceType::OUT_SUBMIX);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
+ media::AudioDeviceType::IN_HEADSET, media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_ANALOG_DOCK());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+ media::AudioDeviceType::IN_HEADSET, media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_DIGITAL_DOCK());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
+ media::AudioDeviceType::IN_ACCESSORY, media::AudioDeviceType::OUT_ACCESSORY,
+ media::AudioDeviceDescription::CONNECTION_USB());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_USB());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
+ media::AudioDeviceType::IN_FM_TUNER, media::AudioDeviceType::OUT_FM);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_ANALOG());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_SPDIF());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_BT_A2DP());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_IP_V4());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_BUS());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
+ media::AudioDeviceType::IN_AFE_PROXY, media::AudioDeviceType::OUT_AFE_PROXY);
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
+ media::AudioDeviceType::IN_HEADSET, media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_USB());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_HDMI_ARC());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
+ media::AudioDeviceType::IN_DEVICE, media::AudioDeviceType::OUT_DEVICE,
+ media::AudioDeviceDescription::CONNECTION_HDMI_EARC());
+ append_AudioDeviceDescription(pairs,
+ AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
+ media::AudioDeviceType::IN_HEADSET, media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_BT_LE());
+ return pairs;
+ }();
+ return pairs;
+}
+
media::AudioFormatDescription make_AudioFormatDescription(media::AudioFormatType type) {
media::AudioFormatDescription result;
result.type = type;
@@ -768,19 +963,55 @@
return pairs;
}
+template<typename S, typename T>
+std::unordered_map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
+ std::unordered_map<S, T> result(v.begin(), v.end());
+ LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+ return result;
+}
+
+template<typename S, typename T>
+std::unordered_map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
+ std::unordered_map<T, S> result;
+ std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
+ [](const std::pair<S, T>& p) {
+ return std::make_pair(p.second, p.first);
+ });
+ LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+ return result;
+}
+
} // namespace
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+ const media::AudioDeviceDescription& aidl) {
+ static const std::unordered_map<media::AudioDeviceDescription, audio_devices_t> m =
+ make_ReverseMap(getAudioDevicePairs());
+ if (auto it = m.find(aidl); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
+ return unexpected(BAD_VALUE);
+ }
+}
+
+ConversionResult<media::AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ audio_devices_t legacy) {
+ static const std::unordered_map<audio_devices_t, media::AudioDeviceDescription> m =
+ make_DirectMap(getAudioDevicePairs());
+ if (auto it = m.find(legacy); it != m.end()) {
+ return it->second;
+ } else {
+ ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
+ __func__, legacy);
+ return unexpected(BAD_VALUE);
+ }
+}
+
ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
const media::AudioFormatDescription& aidl) {
static const std::unordered_map<media::AudioFormatDescription, audio_format_t> m =
- [](const detail::AudioFormatPairs& f) {
- std::unordered_map<media::AudioFormatDescription, audio_format_t> r;
- std::transform(f.begin(), f.end(), std::inserter(r, r.begin()),
- [](const detail::AudioFormatPair& p) {
- return std::make_pair(p.second, p.first);
- });
- return r;
- }(getAudioFormatPairs());
+ make_ReverseMap(getAudioFormatPairs());
if (auto it = m.find(aidl); it != m.end()) {
return it->second;
} else {
@@ -792,9 +1023,7 @@
ConversionResult<media::AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
audio_format_t legacy) {
static const std::unordered_map<audio_format_t, media::AudioFormatDescription> m =
- [](const detail::AudioFormatPairs& f) {
- return std::unordered_map<audio_format_t, media::AudioFormatDescription>(
- f.begin(), f.end()); }(getAudioFormatPairs());
+ make_DirectMap(getAudioFormatPairs());
if (auto it = m.find(legacy); it != m.end()) {
return it->second;
} else {
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 809a26b..a23c844 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -309,6 +309,8 @@
"aidl/android/media/AudioConfigBase.aidl",
"aidl/android/media/AudioContentType.aidl",
"aidl/android/media/AudioDevice.aidl",
+ "aidl/android/media/AudioDeviceDescription.aidl",
+ "aidl/android/media/AudioDeviceType.aidl",
"aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioEncapsulationMode.aidl",
"aidl/android/media/AudioEncapsulationMetadataType.aidl",
diff --git a/media/libaudioclient/aidl/android/media/AudioDeviceDescription.aidl b/media/libaudioclient/aidl/android/media/AudioDeviceDescription.aidl
new file mode 100644
index 0000000..f7548b9
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioDeviceDescription.aidl
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.AudioDeviceType;
+
+parcelable AudioDeviceDescription {
+ /**
+ * Type and directionality of the device. For bidirectional audio devices
+ * two descriptions need to be created, having the same value for
+ * the 'connection' field.
+ *
+ * See 'AudioDeviceType' for the list of supported values.
+ */
+ AudioDeviceType type = AudioDeviceType.NONE;
+ /**
+ * Specifies the type of the connection of the device to the audio system.
+ * Usually it's some kind of a communication protocol, e.g. Bluetooth SCO or
+ * USB. There is a list of connection types recognized by the framework,
+ * defined using 'CONNECTION_' constants. Vendors can add their own
+ * connection types with "vx.<vendor>." prefix.
+ *
+ * When the 'connection' field is left empty and 'type != NONE | DEFAULT',
+ * it is assumed that the device is permanently attached to the audio
+ * system, e.g. a built-in speaker or microphone.
+ *
+ * The 'connection' field must be left empty if 'type' is 'NONE' or
+ * '{IN|OUT}_DEFAULT'.
+ */
+ @utf8InCpp String connection;
+ /**
+ * Analog connection, for example, via 3.5 mm analog jack.
+ */
+ const @utf8InCpp String CONNECTION_ANALOG = "analog";
+ /**
+ * Low-End (Analog) Desk Dock.
+ */
+ const @utf8InCpp String CONNECTION_ANALOG_DOCK = "analog-dock";
+ /**
+ * Bluetooth A2DP connection.
+ */
+ const @utf8InCpp String CONNECTION_BT_A2DP = "bt-a2dp";
+ /**
+ * Bluetooth Low Energy (LE) connection.
+ */
+ const @utf8InCpp String CONNECTION_BT_LE = "bt-le";
+ /**
+ * Bluetooth SCO connection.
+ */
+ const @utf8InCpp String CONNECTION_BT_SCO = "bt-sco";
+ /**
+ * Bus connection. Mostly used in automotive scenarios.
+ */
+ const @utf8InCpp String CONNECTION_BUS = "bus";
+ /**
+ * High-End (Digital) Desk Dock.
+ */
+ const @utf8InCpp String CONNECTION_DIGITAL_DOCK = "digital-dock";
+ /**
+ * HDMI connection.
+ */
+ const @utf8InCpp String CONNECTION_HDMI = "hdmi";
+ /**
+ * HDMI ARC connection.
+ */
+ const @utf8InCpp String CONNECTION_HDMI_ARC = "hdmi-arc";
+ /**
+ * HDMI eARC connection.
+ */
+ const @utf8InCpp String CONNECTION_HDMI_EARC = "hdmi-earc";
+ /**
+ * IP v4 connection.
+ */
+ const @utf8InCpp String CONNECTION_IP_V4 = "ip-v4";
+ /**
+ * SPDIF connection.
+ */
+ const @utf8InCpp String CONNECTION_SPDIF = "spdif";
+ /**
+ * A wireless connection when the actual protocol is unspecified.
+ */
+ const @utf8InCpp String CONNECTION_WIRELESS = "wireless";
+ /**
+ * USB connection.
+ */
+ const @utf8InCpp String CONNECTION_USB = "usb";
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioDeviceType.aidl b/media/libaudioclient/aidl/android/media/AudioDeviceType.aidl
new file mode 100644
index 0000000..4da9fd6
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioDeviceType.aidl
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * The type of the audio device. Only used as part of 'AudioDeviceDescription'
+ * structure.
+ *
+ * Types are divided into "input" and "output" categories. Audio devices that
+ * have both audio input and output, for example, headsets, are represented by a
+ * pair of input and output device types.
+ *
+ * The 'AudioDeviceType' intentionally binds together directionality and 'kind'
+ * of the device to avoid making them fully orthogonal. This is because not all
+ * types of devices are bidirectional, for example, speakers can only be used
+ * for output and microphones can only be used for input (at least, in the
+ * context of the audio framework).
+ */
+@Backing(type="int")
+enum AudioDeviceType {
+ /**
+ * "None" type is a "null" value. All fields of 'AudioDeviceDescription'
+ * must have default / empty / null values.
+ */
+ NONE = 0,
+ /**
+ * The "default" device is used when the client does not have any
+ * preference for a particular device.
+ */
+ IN_DEFAULT = 1,
+ /**
+ * A device implementing Android Open Accessory protocol.
+ */
+ IN_ACCESSORY = 2,
+ /**
+ * Input from a DSP front-end proxy device.
+ */
+ IN_AFE_PROXY = 3,
+ /**
+ * Used when only the connection protocol is known, e.g. a "HDMI Device."
+ */
+ IN_DEVICE = 4,
+ /**
+ * A device providing reference input for echo canceller.
+ */
+ IN_ECHO_REFERENCE = 5,
+ /**
+ * FM Tuner input.
+ */
+ IN_FM_TUNER = 6,
+ /**
+ * A microphone of a headset.
+ */
+ IN_HEADSET = 7,
+ /**
+ * Loopback input.
+ */
+ IN_LOOPBACK = 8,
+ /**
+ * The main microphone (the frontal mic on mobile devices).
+ */
+ IN_MICROPHONE = 9,
+ /**
+ * The secondary microphone (the back mic on mobile devices).
+ */
+ IN_MICROPHONE_BACK = 10,
+ /**
+ * Input from a submix of other streams.
+ */
+ IN_SUBMIX = 11,
+ /**
+ * Audio received via the telephone line.
+ */
+ IN_TELEPHONY_RX = 12,
+ /**
+ * TV Tuner audio input.
+ */
+ IN_TV_TUNER = 13,
+ /**
+ * The "default" device is used when the client does not have any
+ * preference for a particular device.
+ */
+ OUT_DEFAULT = 129,
+ /**
+ * A device implementing Android Open Accessory protocol.
+ */
+ OUT_ACCESSORY = 130,
+ /**
+ * Output from a DSP front-end proxy device.
+ */
+ OUT_AFE_PROXY = 131,
+ /**
+ * Car audio system.
+ */
+ OUT_CARKIT = 132,
+ /**
+ * Used when only the connection protocol is known, e.g. a "HDMI Device."
+ */
+ OUT_DEVICE = 133,
+ /**
+ * The echo canceller device.
+ */
+ OUT_ECHO_CANCELLER = 134,
+ /**
+ * The FM Tuner device.
+ */
+ OUT_FM = 135,
+ /**
+ * Headphones.
+ */
+ OUT_HEADPHONE = 136,
+ /**
+ * Headphones of a headset.
+ */
+ OUT_HEADSET = 137,
+ /**
+ * Hearing aid.
+ */
+ OUT_HEARING_AID = 138,
+ /**
+ * Secondary line level output.
+ */
+ OUT_LINE_AUX = 139,
+ /**
+ * The main speaker.
+ */
+ OUT_SPEAKER = 140,
+ /**
+ * The speaker of a mobile device in the case when it is close to the ear.
+ */
+ OUT_SPEAKER_EARPIECE = 141,
+ /**
+ * The main speaker with overload / overheating protection.
+ */
+ OUT_SPEAKER_SAFE = 142,
+ /**
+ * Output into a submix.
+ */
+ OUT_SUBMIX = 143,
+ /**
+ * Output into a telephone line.
+ */
+ OUT_TELEPHONY_TX = 144,
+}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 305dbc3..422d94f 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -25,6 +25,7 @@
#include <android/media/AudioClient.h>
#include <android/media/AudioConfig.h>
#include <android/media/AudioConfigBase.h>
+#include <android/media/AudioDeviceDescription.h>
#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioEncapsulationMode.h>
#include <android/media/AudioEncapsulationMetadataType.h>
@@ -139,6 +140,11 @@
ConversionResult<media::AudioFormatSys> legacy2aidl_audio_format_t_AudioFormat(
audio_format_t legacy);
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+ const media::AudioDeviceDescription& aidl);
+ConversionResult<media::AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
+ audio_devices_t legacy);
+
ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
const media::AudioFormatDescription& aidl);
ConversionResult<media::AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
diff --git a/media/libaudioclient/include/media/AudioCommonTypes.h b/media/libaudioclient/include/media/AudioCommonTypes.h
index 607b99c..613d6bd 100644
--- a/media/libaudioclient/include/media/AudioCommonTypes.h
+++ b/media/libaudioclient/include/media/AudioCommonTypes.h
@@ -19,6 +19,7 @@
#include <functional>
+#include <android/media/AudioDeviceDescription.h>
#include <android/media/AudioFormatDescription.h>
#include <binder/Parcelable.h>
#include <system/audio.h>
@@ -36,9 +37,18 @@
namespace std {
-// Note: when extending AudioFormatDescription we need to account for the
+// Note: when extending Audio{Device|Format}Description we need to account for the
// possibility of comparison between different versions of it, e.g. a HAL
// may be using a previous version of the AIDL interface.
+template<> struct hash<android::media::AudioDeviceDescription>
+{
+ std::size_t operator()(const android::media::AudioDeviceDescription& add) const noexcept {
+ return hash_combine(
+ std::hash<android::media::AudioDeviceType>{}(add.type),
+ std::hash<std::string>{}(add.connection));
+ }
+};
+
template<> struct hash<android::media::AudioFormatDescription>
{
std::size_t operator()(const android::media::AudioFormatDescription& afd) const noexcept {
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index e4bc9f0..ca609ab 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -24,10 +24,44 @@
namespace {
-size_t afdHash(const media::AudioFormatDescription& afd) {
+size_t hash(const media::AudioDeviceDescription& add) {
+ return std::hash<media::AudioDeviceDescription>{}(add);
+}
+
+size_t hash(const media::AudioFormatDescription& afd) {
return std::hash<media::AudioFormatDescription>{}(afd);
}
+media::AudioDeviceDescription make_AudioDeviceDescription(media::AudioDeviceType type,
+ const std::string& connection = "") {
+ media::AudioDeviceDescription result;
+ result.type = type;
+ result.connection = connection;
+ return result;
+}
+
+media::AudioDeviceDescription make_ADD_None() {
+ return media::AudioDeviceDescription{};
+}
+
+media::AudioDeviceDescription make_ADD_DefaultIn() {
+ return make_AudioDeviceDescription(media::AudioDeviceType::IN_DEFAULT);
+}
+
+media::AudioDeviceDescription make_ADD_DefaultOut() {
+ return make_AudioDeviceDescription(media::AudioDeviceType::OUT_DEFAULT);
+}
+
+media::AudioDeviceDescription make_ADD_WiredHeadset() {
+ return make_AudioDeviceDescription(media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_ANALOG());
+}
+
+media::AudioDeviceDescription make_ADD_BtScoHeadset() {
+ return make_AudioDeviceDescription(media::AudioDeviceType::OUT_HEADSET,
+ media::AudioDeviceDescription::CONNECTION_BT_SCO());
+}
+
media::AudioFormatDescription make_AudioFormatDescription(media::AudioFormatType type) {
media::AudioFormatDescription result;
result.type = type;
@@ -53,6 +87,10 @@
return result;
}
+media::AudioFormatDescription make_AFD_Default() {
+ return media::AudioFormatDescription{};
+}
+
media::AudioFormatDescription make_AFD_Invalid() {
return make_AudioFormatDescription(media::AudioFormatType::SYS_RESERVED_INVALID);
}
@@ -77,25 +115,53 @@
} // namespace
-// Verify that two independently constructed AFDs have the same hash.
-// This ensures that regardless of whether the AFD instance originates
-// from, it can be correctly compared to other AFD instance. Thus,
+// Verify that two independently constructed ADDs/AFDs have the same hash.
+// This ensures that regardless of whether the ADD/AFD instance originates
+// from, it can be correctly compared to other ADD/AFD instance. Thus,
// for example, a 16-bit integer format description provided by HAL
// is identical to the same format description constructed by the framework.
-TEST(audio_aidl_legacy_conversion_tests, AudioFormatDescriptionHashIdentity) {
- EXPECT_EQ(afdHash(make_AFD_Invalid()), afdHash(make_AFD_Invalid()));
- EXPECT_EQ(afdHash(media::AudioFormatDescription{}), afdHash(media::AudioFormatDescription{}));
- EXPECT_EQ(afdHash(make_AFD_Pcm16Bit()), afdHash(make_AFD_Pcm16Bit()));
- EXPECT_NE(afdHash(media::AudioFormatDescription{}), afdHash(make_AFD_Invalid()));
- EXPECT_NE(afdHash(media::AudioFormatDescription{}), afdHash(make_AFD_Pcm16Bit()));
- EXPECT_EQ(afdHash(make_AFD_Bitstream()), afdHash(make_AFD_Bitstream()));
- EXPECT_NE(afdHash(make_AFD_Pcm16Bit()), afdHash(make_AFD_Bitstream()));
- EXPECT_EQ(afdHash(make_AFD_Encap()), afdHash(make_AFD_Encap()));
- EXPECT_NE(afdHash(make_AFD_Pcm16Bit()), afdHash(make_AFD_Encap()));
- EXPECT_EQ(afdHash(make_AFD_Encap_with_Enc()), afdHash(make_AFD_Encap_with_Enc()));
- EXPECT_NE(afdHash(make_AFD_Encap()), afdHash(make_AFD_Encap_with_Enc()));
+class HashIdentityTest : public ::testing::Test {
+ public:
+ template<typename T> void verifyHashIdentity(const std::vector<std::function<T()>>& valueGens) {
+ for (size_t i = 0; i < valueGens.size(); ++i) {
+ for (size_t j = 0; j < valueGens.size(); ++j) {
+ if (i == j) {
+ EXPECT_EQ(hash(valueGens[i]()), hash(valueGens[i]())) << i;
+ } else {
+ EXPECT_NE(hash(valueGens[i]()), hash(valueGens[j]())) << i << ", " << j;
+ }
+ }
+ }
+ }
+};
+
+TEST_F(HashIdentityTest, AudioDeviceDescriptionHashIdentity) {
+ verifyHashIdentity<media::AudioDeviceDescription>({
+ make_ADD_None, make_ADD_DefaultIn, make_ADD_DefaultOut, make_ADD_WiredHeadset,
+ make_ADD_BtScoHeadset});
}
+TEST_F(HashIdentityTest, AudioFormatDescriptionHashIdentity) {
+ verifyHashIdentity<media::AudioFormatDescription>({
+ make_AFD_Default, make_AFD_Invalid, make_AFD_Pcm16Bit, make_AFD_Bitstream,
+ make_AFD_Encap, make_AFD_Encap_with_Enc});
+}
+
+class AudioDeviceDescriptionRoundTripTest :
+ public testing::TestWithParam<media::AudioDeviceDescription> {};
+TEST_P(AudioDeviceDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ auto conv = aidl2legacy_AudioDeviceDescription_audio_devices_t(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_audio_devices_t_AudioDeviceDescription(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioDeviceDescriptionRoundTrip,
+ AudioDeviceDescriptionRoundTripTest,
+ testing::Values(media::AudioDeviceDescription{}, make_ADD_DefaultIn(),
+ make_ADD_DefaultOut(), make_ADD_WiredHeadset(), make_ADD_BtScoHeadset()));
+
class AudioFormatDescriptionRoundTripTest :
public testing::TestWithParam<media::AudioFormatDescription> {};
TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {