Merge "Do not log error if HAL does not support VOIP volume."
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1f7083b..62cf827 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -12,3 +12,4 @@
media/libmediatranscoding/
services/mediatranscoding/
media/libaudioclient/tests/
+ media/libaudiohal/tests/
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index ab25c65..cee44b9 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -31,7 +31,33 @@
],
}
-cc_binary {
+prebuilt_etc {
+ name: "drmserver.zygote64_32.rc",
+ src: "drmserver.zygote64_32.rc",
+ sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+ name: "drmserver.zygote64.rc",
+ src: "drmserver.zygote64.rc",
+ sub_dir: "init/hw",
+}
+
+soong_config_module_type {
+ name: "drmserver_cc_binary",
+ module_type: "cc_binary",
+ config_namespace: "ANDROID",
+ bool_variables: ["TARGET_DYNAMIC_64_32_DRMSERVER"],
+ properties: [
+ "compile_multilib",
+ "init_rc",
+ "multilib.lib32.suffix",
+ "multilib.lib64.suffix",
+ "required",
+ ],
+}
+
+drmserver_cc_binary {
name: "drmserver",
srcs: [
@@ -61,7 +87,27 @@
compile_multilib: "prefer32",
- init_rc: ["drmserver.rc"],
+ soong_config_variables: {
+ TARGET_DYNAMIC_64_32_DRMSERVER: {
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+ required: [
+ "drmserver.zygote64_32.rc",
+ "drmserver.zygote64.rc",
+ ],
+ init_rc: ["drmserver_dynamic.rc"],
+ conditions_default: {
+ init_rc: ["drmserver.rc"],
+ },
+ },
+ },
}
cc_fuzz {
@@ -80,7 +126,6 @@
static_libs: [
"libmediautils",
"liblog",
- "libdl",
"libdrmframeworkcommon",
"libselinux",
"libstagefright_foundation",
@@ -98,4 +143,4 @@
"android-drm-team@google.com",
],
},
-}
\ No newline at end of file
+}
diff --git a/drm/drmserver/drmserver.zygote64.rc b/drm/drmserver/drmserver.zygote64.rc
new file mode 100644
index 0000000..60cd906
--- /dev/null
+++ b/drm/drmserver/drmserver.zygote64.rc
@@ -0,0 +1,6 @@
+service drm /system/bin/drmserver64
+ disabled
+ class main
+ user drm
+ group drm system inet drmrpc readproc
+ task_profiles ProcessCapacityHigh
diff --git a/drm/drmserver/drmserver.zygote64_32.rc b/drm/drmserver/drmserver.zygote64_32.rc
new file mode 100644
index 0000000..c881acf
--- /dev/null
+++ b/drm/drmserver/drmserver.zygote64_32.rc
@@ -0,0 +1,6 @@
+service drm /system/bin/drmserver32
+ disabled
+ class main
+ user drm
+ group drm system inet drmrpc readproc
+ task_profiles ProcessCapacityHigh
diff --git a/drm/drmserver/drmserver_dynamic.rc b/drm/drmserver/drmserver_dynamic.rc
new file mode 100644
index 0000000..bfaada1
--- /dev/null
+++ b/drm/drmserver/drmserver_dynamic.rc
@@ -0,0 +1,7 @@
+import /system/etc/init/hw/drmserver.${ro.zygote}.rc
+
+on property:drm.service.enabled=true
+ start drm
+
+on property:drm.service.enabled=1
+ start drm
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 0cfd128..17e6e98 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -18,6 +18,7 @@
#include <algorithm>
#include <map>
+#include <sstream>
#include <utility>
#include <vector>
@@ -50,6 +51,7 @@
using ::android::status_t;
using ::android::base::unexpected;
+using media::audio::common::AudioAttributes;
using media::audio::common::AudioChannelLayout;
using media::audio::common::AudioConfig;
using media::audio::common::AudioConfigBase;
@@ -62,6 +64,7 @@
using media::audio::common::AudioEncapsulationMetadataType;
using media::audio::common::AudioEncapsulationMode;
using media::audio::common::AudioEncapsulationType;
+using media::audio::common::AudioFlag;
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioFormatType;
using media::audio::common::AudioGain;
@@ -95,6 +98,20 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Converters
+namespace {
+
+std::vector<std::string> splitString(const std::string& s, char separator) {
+ std::istringstream iss(s);
+ std::string t;
+ std::vector<std::string> result;
+ while (std::getline(iss, t, separator)) {
+ result.push_back(std::move(t));
+ }
+ return result;
+}
+
+} // namespace
+
::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
if (aidl.size() > maxSize - 1) {
return BAD_VALUE;
@@ -262,12 +279,17 @@
DEFINE_INPUT_LAYOUT(MONO),
DEFINE_INPUT_LAYOUT(STEREO),
+ DEFINE_INPUT_LAYOUT(2POINT1),
DEFINE_INPUT_LAYOUT(FRONT_BACK),
+ DEFINE_INPUT_LAYOUT(TRI),
+ DEFINE_INPUT_LAYOUT(3POINT1),
// AUDIO_CHANNEL_IN_6 not supported
DEFINE_INPUT_LAYOUT(2POINT0POINT2),
DEFINE_INPUT_LAYOUT(2POINT1POINT2),
DEFINE_INPUT_LAYOUT(3POINT0POINT2),
DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+ DEFINE_INPUT_LAYOUT(QUAD),
+ DEFINE_INPUT_LAYOUT(PENTA),
DEFINE_INPUT_LAYOUT(5POINT1)
#undef DEFINE_INPUT_LAYOUT
};
@@ -1791,6 +1813,156 @@
return unexpected(BAD_VALUE);
}
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(AudioFlag aidl) {
+ switch (aidl) {
+ case AudioFlag::NONE:
+ return AUDIO_FLAG_NONE;
+ case AudioFlag::AUDIBILITY_ENFORCED:
+ return AUDIO_FLAG_AUDIBILITY_ENFORCED;
+ // The is no AudioFlag::SECURE, see the comment in the AudioFlag.aidl
+ // return AUDIO_FLAG_SECURE;
+ case AudioFlag::SCO:
+ return AUDIO_FLAG_SCO;
+ case AudioFlag::BEACON:
+ return AUDIO_FLAG_BEACON;
+ case AudioFlag::HW_AV_SYNC:
+ return AUDIO_FLAG_HW_AV_SYNC;
+ case AudioFlag::HW_HOTWORD:
+ return AUDIO_FLAG_HW_HOTWORD;
+ case AudioFlag::BYPASS_INTERRUPTION_POLICY:
+ return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
+ case AudioFlag::BYPASS_MUTE:
+ return AUDIO_FLAG_BYPASS_MUTE;
+ case AudioFlag::LOW_LATENCY:
+ return AUDIO_FLAG_LOW_LATENCY;
+ case AudioFlag::DEEP_BUFFER:
+ return AUDIO_FLAG_DEEP_BUFFER;
+ case AudioFlag::NO_MEDIA_PROJECTION:
+ return AUDIO_FLAG_NO_MEDIA_PROJECTION;
+ case AudioFlag::MUTE_HAPTIC:
+ return AUDIO_FLAG_MUTE_HAPTIC;
+ case AudioFlag::NO_SYSTEM_CAPTURE:
+ return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+ case AudioFlag::CAPTURE_PRIVATE:
+ return AUDIO_FLAG_CAPTURE_PRIVATE;
+ case AudioFlag::CONTENT_SPATIALIZED:
+ return AUDIO_FLAG_CONTENT_SPATIALIZED;
+ case AudioFlag::NEVER_SPATIALIZE:
+ return AUDIO_FLAG_NEVER_SPATIALIZE;
+ case AudioFlag::CALL_REDIRECTION:
+ return AUDIO_FLAG_CALL_REDIRECTION;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
+ switch (legacy) {
+ case AUDIO_FLAG_NONE:
+ return AudioFlag::NONE;
+ case AUDIO_FLAG_AUDIBILITY_ENFORCED:
+ return AudioFlag::AUDIBILITY_ENFORCED;
+ case AUDIO_FLAG_SECURE:
+ return unexpected(BAD_VALUE);
+ case AUDIO_FLAG_SCO:
+ return AudioFlag::SCO;
+ case AUDIO_FLAG_BEACON:
+ return AudioFlag::BEACON;
+ case AUDIO_FLAG_HW_AV_SYNC:
+ return AudioFlag::HW_AV_SYNC;
+ case AUDIO_FLAG_HW_HOTWORD:
+ return AudioFlag::HW_HOTWORD;
+ case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
+ return AudioFlag::BYPASS_INTERRUPTION_POLICY;
+ case AUDIO_FLAG_BYPASS_MUTE:
+ return AudioFlag::BYPASS_MUTE;
+ case AUDIO_FLAG_LOW_LATENCY:
+ return AudioFlag::LOW_LATENCY;
+ case AUDIO_FLAG_DEEP_BUFFER:
+ return AudioFlag::DEEP_BUFFER;
+ case AUDIO_FLAG_NO_MEDIA_PROJECTION:
+ return AudioFlag::NO_MEDIA_PROJECTION;
+ case AUDIO_FLAG_MUTE_HAPTIC:
+ return AudioFlag::MUTE_HAPTIC;
+ case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
+ return AudioFlag::NO_SYSTEM_CAPTURE;
+ case AUDIO_FLAG_CAPTURE_PRIVATE:
+ return AudioFlag::CAPTURE_PRIVATE;
+ case AUDIO_FLAG_CONTENT_SPATIALIZED:
+ return AudioFlag::CONTENT_SPATIALIZED;
+ case AUDIO_FLAG_NEVER_SPATIALIZE:
+ return AudioFlag::NEVER_SPATIALIZE;
+ case AUDIO_FLAG_CALL_REDIRECTION:
+ return AudioFlag::CALL_REDIRECTION;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
+ return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, AudioFlag>(
+ aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_bitmask<AudioFlag>,
+ enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
+ return convertBitmask<int32_t, audio_flags_mask_t, AudioFlag, audio_flags_mask_t>(
+ legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
+ indexToEnum_bitmask<audio_flags_mask_t>,
+ enumToMask_bitmask<int32_t, AudioFlag>);
+}
+
+ConversionResult<std::string>
+aidl2legacy_AudioTags_string(const std::vector<std::string>& aidl) {
+ std::ostringstream tagsBuffer;
+ bool hasValue = false;
+ for (const auto& tag : aidl) {
+ if (hasValue) {
+ tagsBuffer << AUDIO_ATTRIBUTES_TAGS_SEPARATOR;
+ }
+ if (strchr(tag.c_str(), AUDIO_ATTRIBUTES_TAGS_SEPARATOR) == nullptr) {
+ tagsBuffer << tag;
+ hasValue = true;
+ } else {
+ ALOGE("Tag is ill-formed: \"%s\"", tag.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ }
+ return tagsBuffer.str();
+}
+
+ConversionResult<std::vector<std::string>>
+legacy2aidl_string_AudioTags(const std::string& legacy) {
+ return splitString(legacy, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+}
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributes_audio_attributes_t(const AudioAttributes& aidl) {
+ audio_attributes_t legacy;
+ legacy.content_type = VALUE_OR_RETURN(
+ aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
+ legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+ legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
+ auto tagsString = VALUE_OR_RETURN(aidl2legacy_AudioTags_string(aidl.tags));
+ RETURN_IF_ERROR(aidl2legacy_string(tagsString, legacy.tags, sizeof(legacy.tags)));
+ return legacy;
+}
+
+ConversionResult<AudioAttributes>
+legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy) {
+ AudioAttributes aidl;
+ aidl.contentType = VALUE_OR_RETURN(
+ legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
+ aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+ aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source));
+ aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
+ auto tagsString = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
+ aidl.tags = VALUE_OR_RETURN(legacy2aidl_string_AudioTags(tagsString));
+ return aidl;
+}
ConversionResult<audio_encapsulation_mode_t>
aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
index 36f6128..ecd2e5e 100644
--- a/media/audioaidlconversion/AidlConversionNdkCpp.cpp
+++ b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
@@ -15,6 +15,7 @@
*/
#include <algorithm>
+#include <regex>
#include <type_traits>
#define LOG_TAG "AidlConversionNdkCpp"
@@ -34,6 +35,24 @@
namespace {
+bool isVendorExtension(const std::string& s) {
+ // Per definition in AudioAttributes.aidl and {Playback|Record}TrackMetadata.aidl
+ static const std::regex vendorExtension("VX_[A-Z0-9]{3,}_[_A-Z0-9]+");
+ return std::regex_match(s.begin(), s.end(), vendorExtension);
+}
+
+inline bool isNotVendorExtension(const std::string& s) { return !isVendorExtension(s); }
+
+void filterOutNonVendorTagsInPlace(std::vector<std::string>& tags) {
+ if (std::find_if(tags.begin(), tags.end(), isNotVendorExtension) == tags.end()) {
+ return;
+ }
+ std::vector<std::string> temp;
+ temp.reserve(tags.size());
+ std::copy_if(tags.begin(), tags.end(), std::back_inserter(temp), isVendorExtension);
+ tags = std::move(temp);
+}
+
// cpp2ndk and ndk2cpp are universal converters which work for any type,
// however they are not the most efficient way to convert due to extra
// marshaling / unmarshaling step.
@@ -99,12 +118,15 @@
} // namespace
-#define GENERATE_CONVERTERS(packageName, className) \
- ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+#define GENERATE_CONVERTERS(packageName, className) \
+ GENERATE_CONVERTERS_IMPL(packageName, _, className)
+
+#define GENERATE_CONVERTERS_IMPL(packageName, prefix, className) \
+ ConversionResult<::aidl::packageName::className> cpp2ndk##prefix##className( \
const ::packageName::className& cpp) { \
return cpp2ndk<::aidl::packageName::className>(cpp); \
} \
- ConversionResult<::packageName::className> ndk2cpp_##className( \
+ ConversionResult<::packageName::className> ndk2cpp##prefix##className( \
const ::aidl::packageName::className& ndk) { \
return ndk2cpp<::packageName::className>(ndk); \
}
@@ -120,9 +142,46 @@
}
GENERATE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
-GENERATE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+GENERATE_CONVERTERS_IMPL(android::media::audio::common, _Impl_, AudioHalEngineConfig);
GENERATE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMode);
GENERATE_CONVERTERS(android::media::audio::common, AudioPort);
+namespace {
+
+// Filter out all AudioAttributes tags that do not conform to the vendor extension pattern.
+template<typename T>
+void filterOutNonVendorTags(T& audioHalEngineConfig) {
+ for (auto& strategy : audioHalEngineConfig.productStrategies) {
+ for (auto& group : strategy.attributesGroups) {
+ for (auto& attr : group.attributes) {
+ filterOutNonVendorTagsInPlace(attr.tags);
+ }
+ }
+ }
+}
+
+} // namespace
+
+ConversionResult<::aidl::android::media::audio::common::AudioHalEngineConfig>
+cpp2ndk_AudioHalEngineConfig(const ::android::media::audio::common::AudioHalEngineConfig& cpp) {
+ auto conv = cpp2ndk_Impl_AudioHalEngineConfig(cpp);
+ if (conv.ok()) {
+ filterOutNonVendorTags(conv.value());
+ }
+ return conv;
+}
+
+ConversionResult<::android::media::audio::common::AudioHalEngineConfig>
+ndk2cpp_AudioHalEngineConfig(
+ const ::aidl::android::media::audio::common::AudioHalEngineConfig& ndk) {
+ auto conv = ndk2cpp_Impl_AudioHalEngineConfig(ndk);
+ if (conv.ok()) {
+ filterOutNonVendorTags(conv.value());
+ }
+ return conv;
+}
+
+
} // namespace android
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index 903b88a..216bc12 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,6 +1,7 @@
{
"presubmit": [
{
+ "name": "audio_aidl_conversion_tests",
"name": "audio_aidl_ndk_conversion_tests",
"name": "audio_aidl_ndk_cpp_conversion_tests"
}
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index ec1f75c..7268464 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -37,6 +37,7 @@
#define PREFIX(f) <f>
#endif
+#include PREFIX(android/media/audio/common/AudioAttributes.h)
#include PREFIX(android/media/audio/common/AudioChannelLayout.h)
#include PREFIX(android/media/audio/common/AudioConfig.h)
#include PREFIX(android/media/audio/common/AudioConfigBase.h)
@@ -46,6 +47,7 @@
#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFlag.h)
#include PREFIX(android/media/audio/common/AudioFormatDescription.h)
#include PREFIX(android/media/audio/common/AudioGain.h)
#include PREFIX(android/media/audio/common/AudioGainConfig.h)
@@ -288,6 +290,11 @@
ConversionResult<media::audio::common::AudioOutputFlags>
legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+ConversionResult<audio_stream_type_t>
+aidl2legacy_AudioStreamType_audio_stream_type_t(media::audio::common::AudioStreamType aidl);
+ConversionResult<media::audio::common::AudioStreamType>
+legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
+
// This type is unnamed in the original definition, thus we name it here.
using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
ConversionResult<audio_port_config_mix_ext_usecase>
@@ -350,6 +357,26 @@
ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
audio_usage_t legacy);
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(media::audio::common::AudioFlag aidl);
+ConversionResult<media::audio::common::AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
+
+ConversionResult<std::string>
+aidl2legacy_AudioTags_string(const std::vector<std::string>& aidl);
+ConversionResult<std::vector<std::string>>
+legacy2aidl_string_AudioTags(const std::string& legacy);
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributes_audio_attributes_t(const media::audio::common::AudioAttributes& aidl);
+ConversionResult<media::audio::common::AudioAttributes>
+legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy);
+
ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
const media::audio::common::AudioUuid &aidl);
ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
index 09f1c22..f4822aa 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
@@ -23,11 +23,13 @@
#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
#include <aidl/android/media/audio/common/AudioMMapPolicyInfo.h>
#include <aidl/android/media/audio/common/AudioMMapPolicyType.h>
+#include <aidl/android/media/audio/common/AudioMode.h>
#include <aidl/android/media/audio/common/AudioPort.h>
#include <android/media/audio/common/AudioFormatDescription.h>
#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioMode.h>
#include <android/media/audio/common/AudioPort.h>
#include <media/AidlConversionUtil.h>
@@ -43,6 +45,7 @@
DECLARE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMode);
DECLARE_CONVERTERS(android::media::audio::common, AudioPort);
#undef DECLARE_CONVERTERS
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index f49f681..656d76a 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -119,6 +119,20 @@
}
/**
+ * A generic template that helps convert containers of convertible types without
+ * using an intermediate container.
+ */
+template<typename InputContainer, typename OutputContainer, typename Func>
+::android::status_t convertContainer(const InputContainer& input, OutputContainer* output,
+ const Func& itemConversion) {
+ auto ins = std::inserter(*output, output->begin());
+ for (const auto& item : input) {
+ *ins = VALUE_OR_RETURN_STATUS(itemConversion(item));
+ }
+ return ::android::OK;
+}
+
+/**
* A generic template that helps convert containers of convertible types.
*/
template<typename OutputContainer, typename InputContainer, typename Func>
@@ -208,6 +222,34 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities for handling bitmasks.
+// Some AIDL enums are specified using bit indices, for example:
+// `AidlEnum { FOO = 0, BAR = 1, BAZ = 2' }`
+// while corresponding legacy types universally uses actual bitmasks, for example:
+// `enum legacy_enum_t { LEGACY_FOO = 1 << 0, LEGACY_BAR = 1 << 1, LEGACY_BAZ = 1 << 2 }`
+// There is also the third type used to store the resulting mask, which is combined
+// from individual bits. In AIDL this is typically an int (`int32_t`), in legacy types this
+// is often the enum type itself (although, strictly this is not correct since masks are not
+// declared as part of the enum type). The bit index value always has an integer type.
+//
+// `indexToEnum_index` constructs an instance of the enum from an index,
+// for example `AidlEnum::BAR` from `1`.
+// `indexToEnum_bitmask` produces a corresponding legacy bitmask enum instance,
+// for example, `LEGACY_BAR` (`2`) from `1`.
+// `enumToMask_bitmask` simply casts an enum type to a bitmask type.
+// `enumToMask_index` creates a mask from an enum type which specifies an index.
+//
+// All these functions can be plugged into `convertBitmask`. For example, to implement
+// conversion from `AidlEnum` to `legacy_enum_t`, with a mask stored in `int32_t`,
+// the following call needs to be made:
+// convertBitmask<legacy_enum_t /*DestMask*/, int32_t /*SrcMask*/,
+// legacy_enum_t /*DestEnum*/, AidlEnum /*SrcEnum*/>(
+// maskField /*int32_t*/, aidl2legacy_AidlEnum_legacy_enum_t /*enumConversion*/,
+// indexToEnum_index<AidlEnum> /*srcIndexToEnum*/,
+// enumToMask_bitmask<legacy_enum_t, legacy_enum_t> /*destEnumToMask*/)
+//
+// The only extra function needed is for mapping between corresponding enum values
+// of the AidlEnum and the legacy_enum_t. Note that the mapping is between values
+// of enums, for example, `AidlEnum::BAZ` maps to `LEGACY_BAZ` and vice versa.
template<typename Enum>
Enum indexToEnum_index(int index) {
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
index c505e60..60727b4 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
namespace {
@@ -89,3 +90,48 @@
ASSERT_EQ(1, convBack.value().tags.size());
EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
}
+
+class AudioTagsRoundTripTest : public testing::TestWithParam<std::vector<std::string>>
+{
+};
+TEST_P(AudioTagsRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto& initial = GetParam();
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_string_AudioTags(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioTagsRoundTrip, AudioTagsRoundTripTest,
+ testing::Values(std::vector<std::string>{},
+ std::vector<std::string>{"VX_GOOGLE_41"},
+ std::vector<std::string>{"VX_GOOGLE_41", "VX_GOOGLE_42"}));
+
+TEST(AudioTags, NonVendorTagsAllowed) {
+ const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+ const std::vector<std::string> initial{"random_string", "VX_GOOGLE_42"};
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ ASSERT_TRUE(conv.ok());
+ EXPECT_EQ("random_string" + separator + "VX_GOOGLE_42", conv.value());
+}
+
+TEST(AudioTags, IllFormedAidlTag) {
+ const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+ {
+ const std::vector<std::string> initial{"VX_GOOGLE" + separator + "42", "VX_GOOGLE_42"};
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ if (conv.ok()) {
+ EXPECT_EQ("VX_GOOGLE_42", conv.value());
+ }
+ // Failing this conversion is also OK. The result depends on whether the conversion
+ // only passes through vendor tags.
+ }
+ {
+ const std::vector<std::string> initial{
+ "random_string", "random" + separator + "string", "VX_GOOGLE_42"};
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ if (conv.ok()) {
+ EXPECT_EQ("VX_GOOGLE_42", conv.value());
+ }
+ }
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
index 735a14b..206c35b 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
@@ -125,3 +125,12 @@
INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip, AudioFormatDescriptionRoundTripTest,
testing::Values(make_AFD_Invalid(), make_AFD_Default(), make_AFD_Pcm16Bit(),
make_AFD_Bitstream(), make_AFD_Encap(), make_AFD_Encap_with_Enc()));
+
+TEST(AudioPortRoundTripTest, Ndk2Cpp2Ndk) {
+ const AudioPort initial;
+ auto conv = ndk2cpp_AudioPort(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = cpp2ndk_AudioPort(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index e3db5b4..1e3bfe0 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -50,6 +50,8 @@
int main(int argc __unused, char **argv)
{
+ ALOGD("%s: starting", __func__);
+ const auto startTime = std::chrono::steady_clock::now();
// TODO: update with refined parameters
limitProcessMemory(
"audio.maxmem", /* "ro.audio.maxmem", property that defines limit */
@@ -144,11 +146,36 @@
setpgid(0, 0); // but if I die first, don't kill my parent
}
android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
- sp<ProcessState> proc(ProcessState::self());
+
+ // Ensure threads for possible callbacks. Note that get_audio_flinger() does
+ // this automatically when called from AudioPolicy, but we do this anyways here.
+ ProcessState::self()->startThreadPool();
+
+ // Instantiating AudioFlinger (making it public, e.g. through ::initialize())
+ // and then instantiating AudioPolicy (and making it public)
+ // leads to situations where AudioFlinger is accessed remotely before
+ // AudioPolicy is initialized. Not only might this
+ // cause inaccurate results, but if AudioPolicy has slow audio HAL
+ // initialization, it can cause a TimeCheck abort to occur on an AudioFlinger
+ // call which tries to access AudioPolicy.
+ //
+ // We create AudioFlinger and AudioPolicy locally then make it public to ServiceManager.
+ // This requires both AudioFlinger and AudioPolicy to be in-proc.
+ //
+ const auto af = sp<AudioFlinger>::make();
+ const auto afAdapter = sp<AudioFlingerServerAdapter>::make(af);
+ ALOGD("%s: AudioFlinger created", __func__);
+ ALOGW_IF(AudioSystem::setLocalAudioFlinger(af) != OK,
+ "%s: AudioSystem already has an AudioFlinger instance!", __func__);
+ const auto aps = sp<AudioPolicyService>::make();
+ ALOGD("%s: AudioPolicy created", __func__);
+
+ // Add AudioFlinger and AudioPolicy to ServiceManager.
sp<IServiceManager> sm = defaultServiceManager();
- ALOGI("ServiceManager: %p", sm.get());
- AudioFlinger::instantiate();
- AudioPolicyService::instantiate();
+ sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME), afAdapter,
+ false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+ sm->addService(String16(AudioPolicyService::getServiceName()), aps,
+ false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
// AAudioService should only be used in OC-MR1 and later.
// And only enable the AAudioService if the system MMAP policy explicitly allows it.
@@ -156,7 +183,6 @@
// If we cannot get audio flinger here, there must be some serious problems. In that case,
// attempting to call audio flinger on a null pointer could make the process crash
// and attract attentions.
- sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
std::vector<AudioMMapPolicyInfo> policyInfos;
status_t status = af->getMmapPolicyInfos(
AudioMMapPolicyType::DEFAULT, &policyInfos);
@@ -169,11 +195,14 @@
})) {
AAudioService::instantiate();
} else {
- ALOGD("Do not init aaudio service, status %d, policy info size %zu",
- status, policyInfos.size());
+ ALOGD("%s: Do not init aaudio service, status %d, policy info size %zu",
+ __func__, status, policyInfos.size());
}
-
- ProcessState::self()->startThreadPool();
+ const auto endTime = std::chrono::steady_clock::now();
+ using FloatMillis = std::chrono::duration<float, std::milli>;
+ const float timeTaken = std::chrono::duration_cast<FloatMillis>(
+ endTime - startTime).count();
+ ALOGI("%s: initialization done in %.3f ms, joining thread pool", __func__, timeTaken);
IPCThreadState::self()->joinThreadPool();
}
}
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index e8969dd..3caa258 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2543,43 +2543,6 @@
}
void CCodec::initiateReleaseIfStuck() {
- bool tunneled = false;
- bool isMediaTypeKnown = false;
- {
- static const std::set<std::string> kKnownMediaTypes{
- MIMETYPE_VIDEO_VP8,
- MIMETYPE_VIDEO_VP9,
- MIMETYPE_VIDEO_AV1,
- MIMETYPE_VIDEO_AVC,
- MIMETYPE_VIDEO_HEVC,
- MIMETYPE_VIDEO_MPEG4,
- MIMETYPE_VIDEO_H263,
- MIMETYPE_VIDEO_MPEG2,
- MIMETYPE_VIDEO_RAW,
- MIMETYPE_VIDEO_DOLBY_VISION,
-
- MIMETYPE_AUDIO_AMR_NB,
- MIMETYPE_AUDIO_AMR_WB,
- MIMETYPE_AUDIO_MPEG,
- MIMETYPE_AUDIO_AAC,
- MIMETYPE_AUDIO_QCELP,
- MIMETYPE_AUDIO_VORBIS,
- MIMETYPE_AUDIO_OPUS,
- MIMETYPE_AUDIO_G711_ALAW,
- MIMETYPE_AUDIO_G711_MLAW,
- MIMETYPE_AUDIO_RAW,
- MIMETYPE_AUDIO_FLAC,
- MIMETYPE_AUDIO_MSGSM,
- MIMETYPE_AUDIO_AC3,
- MIMETYPE_AUDIO_EAC3,
-
- MIMETYPE_IMAGE_ANDROID_HEIC,
- };
- Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
- const std::unique_ptr<Config> &config = *configLocked;
- tunneled = config->mTunneled;
- isMediaTypeKnown = (kKnownMediaTypes.count(config->mCodingMediaType) != 0);
- }
std::string name;
bool pendingDeadline = false;
{
@@ -2591,16 +2554,6 @@
pendingDeadline = true;
}
}
- if (!tunneled && isMediaTypeKnown && name.empty()) {
- constexpr std::chrono::steady_clock::duration kWorkDurationThreshold = 3s;
- std::chrono::steady_clock::duration elapsed = mChannel->elapsed();
- if (elapsed >= kWorkDurationThreshold) {
- name = "queue";
- }
- if (elapsed > 0s) {
- pendingDeadline = true;
- }
- }
if (name.empty()) {
// We're not stuck.
if (pendingDeadline) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 137507b..be00d1e 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1989,6 +1989,7 @@
newInputDelay.value_or(input->inputDelay) +
newPipelineDelay.value_or(input->pipelineDelay) +
kSmoothnessFactor;
+ input->inputDelay = newInputDelay.value_or(input->inputDelay);
if (input->buffers->isArrayMode()) {
if (input->numSlots >= newNumSlots) {
input->numExtraSlots = 0;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 8f0f1c9..3eb2e63 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -478,19 +478,56 @@
mInitCheck = NO_INIT;
return;
case C2PlanarLayout::TYPE_RGB:
- ALOGD("Converter: unrecognized color format "
- "(client %d component %d) for RGB layout",
- mClientColorFormat, mComponentColorFormat);
- mInitCheck = NO_INIT;
+ mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
// TODO: support MediaImage layout
- return;
+ switch (mClientColorFormat) {
+ case COLOR_FormatSurface:
+ case COLOR_FormatRGBFlexible:
+ case COLOR_Format24bitBGR888:
+ case COLOR_Format24bitRGB888:
+ ALOGD("Converter: accept color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ break;
+ default:
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ if (layout.numPlanes != 3) {
+ ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ break;
case C2PlanarLayout::TYPE_RGBA:
- ALOGD("Converter: unrecognized color format "
- "(client %d component %d) for RGBA layout",
- mClientColorFormat, mComponentColorFormat);
- mInitCheck = NO_INIT;
+ mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
// TODO: support MediaImage layout
- return;
+ switch (mClientColorFormat) {
+ case COLOR_FormatSurface:
+ case COLOR_FormatRGBAFlexible:
+ case COLOR_Format32bitABGR8888:
+ case COLOR_Format32bitARGB8888:
+ case COLOR_Format32bitBGRA8888:
+ ALOGD("Converter: accept color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ break;
+ default:
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ if (layout.numPlanes != 4) {
+ ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ break;
default:
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
if (layout.numPlanes == 1) {
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index b32667e..bd10e44 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -480,129 +480,6 @@
return aidl;
}
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
- switch (aidl) {
- case media::AudioFlag::AUDIBILITY_ENFORCED:
- return AUDIO_FLAG_AUDIBILITY_ENFORCED;
- case media::AudioFlag::SECURE:
- return AUDIO_FLAG_SECURE;
- case media::AudioFlag::SCO:
- return AUDIO_FLAG_SCO;
- case media::AudioFlag::BEACON:
- return AUDIO_FLAG_BEACON;
- case media::AudioFlag::HW_AV_SYNC:
- return AUDIO_FLAG_HW_AV_SYNC;
- case media::AudioFlag::HW_HOTWORD:
- return AUDIO_FLAG_HW_HOTWORD;
- case media::AudioFlag::BYPASS_INTERRUPTION_POLICY:
- return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
- case media::AudioFlag::BYPASS_MUTE:
- return AUDIO_FLAG_BYPASS_MUTE;
- case media::AudioFlag::LOW_LATENCY:
- return AUDIO_FLAG_LOW_LATENCY;
- case media::AudioFlag::DEEP_BUFFER:
- return AUDIO_FLAG_DEEP_BUFFER;
- case media::AudioFlag::NO_MEDIA_PROJECTION:
- return AUDIO_FLAG_NO_MEDIA_PROJECTION;
- case media::AudioFlag::MUTE_HAPTIC:
- return AUDIO_FLAG_MUTE_HAPTIC;
- case media::AudioFlag::NO_SYSTEM_CAPTURE:
- return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
- case media::AudioFlag::CAPTURE_PRIVATE:
- return AUDIO_FLAG_CAPTURE_PRIVATE;
- case media::AudioFlag::CONTENT_SPATIALIZED:
- return AUDIO_FLAG_CONTENT_SPATIALIZED;
- case media::AudioFlag::NEVER_SPATIALIZE:
- return AUDIO_FLAG_NEVER_SPATIALIZE;
- case media::AudioFlag::CALL_REDIRECTION:
- return AUDIO_FLAG_CALL_REDIRECTION;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioFlag>
-legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
- switch (legacy) {
- case AUDIO_FLAG_NONE:
- return unexpected(BAD_VALUE);
- case AUDIO_FLAG_AUDIBILITY_ENFORCED:
- return media::AudioFlag::AUDIBILITY_ENFORCED;
- case AUDIO_FLAG_SECURE:
- return media::AudioFlag::SECURE;
- case AUDIO_FLAG_SCO:
- return media::AudioFlag::SCO;
- case AUDIO_FLAG_BEACON:
- return media::AudioFlag::BEACON;
- case AUDIO_FLAG_HW_AV_SYNC:
- return media::AudioFlag::HW_AV_SYNC;
- case AUDIO_FLAG_HW_HOTWORD:
- return media::AudioFlag::HW_HOTWORD;
- case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
- return media::AudioFlag::BYPASS_INTERRUPTION_POLICY;
- case AUDIO_FLAG_BYPASS_MUTE:
- return media::AudioFlag::BYPASS_MUTE;
- case AUDIO_FLAG_LOW_LATENCY:
- return media::AudioFlag::LOW_LATENCY;
- case AUDIO_FLAG_DEEP_BUFFER:
- return media::AudioFlag::DEEP_BUFFER;
- case AUDIO_FLAG_NO_MEDIA_PROJECTION:
- return media::AudioFlag::NO_MEDIA_PROJECTION;
- case AUDIO_FLAG_MUTE_HAPTIC:
- return media::AudioFlag::MUTE_HAPTIC;
- case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
- return media::AudioFlag::NO_SYSTEM_CAPTURE;
- case AUDIO_FLAG_CAPTURE_PRIVATE:
- return media::AudioFlag::CAPTURE_PRIVATE;
- case AUDIO_FLAG_CONTENT_SPATIALIZED:
- return media::AudioFlag::CONTENT_SPATIALIZED;
- case AUDIO_FLAG_NEVER_SPATIALIZE:
- return media::AudioFlag::NEVER_SPATIALIZE;
- case AUDIO_FLAG_CALL_REDIRECTION:
- return media::AudioFlag::CALL_REDIRECTION;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
- return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, media::AudioFlag>(
- aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_index<media::AudioFlag>,
- enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
- return convertBitmask<int32_t, audio_flags_mask_t, media::AudioFlag, audio_flags_mask_t>(
- legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
- indexToEnum_bitmask<audio_flags_mask_t>,
- enumToMask_index<int32_t, media::AudioFlag>);
-}
-
-ConversionResult<audio_attributes_t>
-aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl) {
- audio_attributes_t legacy;
- legacy.content_type = VALUE_OR_RETURN(
- aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
- legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
- legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
- RETURN_IF_ERROR(aidl2legacy_string(aidl.tags, legacy.tags, sizeof(legacy.tags)));
- return legacy;
-}
-
-ConversionResult<media::AudioAttributesInternal>
-legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy) {
- media::AudioAttributesInternal aidl;
- aidl.contentType = VALUE_OR_RETURN(
- legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
- aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
- aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source));
- aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
- aidl.tags = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
- return aidl;
-}
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
sp<IMemory> legacy;
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index dc7afdb..9664271 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -48,7 +48,7 @@
cc_library {
name: "libaudiopolicy",
srcs: [
- "AudioAttributes.cpp",
+ "VolumeGroupAttributes.cpp",
"AudioPolicy.cpp",
"AudioProductStrategy.cpp",
"AudioVolumeGroup.cpp",
@@ -281,15 +281,15 @@
double_loadable: true,
local_include_dir: "aidl",
srcs: [
- "aidl/android/media/AudioAttributesInternal.aidl",
"aidl/android/media/AudioClient.aidl",
"aidl/android/media/AudioDirectMode.aidl",
- "aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
"aidl/android/media/AudioHalVersion.aidl",
+ "aidl/android/media/AudioHwModule.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
"aidl/android/media/AudioPatchFw.aidl",
+ "aidl/android/media/AudioPolicyConfig.aidl",
"aidl/android/media/AudioPortFw.aidl",
"aidl/android/media/AudioPortSys.aidl",
"aidl/android/media/AudioPortConfigFw.aidl",
diff --git a/media/libaudioclient/AudioProductStrategy.cpp b/media/libaudioclient/AudioProductStrategy.cpp
index ecd423a..d9fd58c 100644
--- a/media/libaudioclient/AudioProductStrategy.cpp
+++ b/media/libaudioclient/AudioProductStrategy.cpp
@@ -18,7 +18,7 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <media/AudioProductStrategy.h>
-#include <media/AudioAttributes.h>
+#include <media/VolumeGroupAttributes.h>
#include <media/PolicyAidlConversion.h>
namespace android {
@@ -42,8 +42,8 @@
aidl.name = legacy.getName();
aidl.audioAttributes = VALUE_OR_RETURN(
convertContainer<std::vector<media::AudioAttributesEx>>(
- legacy.getAudioAttributes(),
- legacy2aidl_AudioAttributes_AudioAttributesEx));
+ legacy.getVolumeGroupAttributes(),
+ legacy2aidl_VolumeGroupAttributes_AudioAttributesEx));
aidl.id = VALUE_OR_RETURN(legacy2aidl_product_strategy_t_int32_t(legacy.getId()));
return aidl;
}
@@ -53,32 +53,57 @@
return AudioProductStrategy(
aidl.name,
VALUE_OR_RETURN(
- convertContainer<std::vector<AudioAttributes>>(
+ convertContainer<std::vector<VolumeGroupAttributes>>(
aidl.audioAttributes,
- aidl2legacy_AudioAttributesEx_AudioAttributes)),
+ aidl2legacy_AudioAttributesEx_VolumeGroupAttributes)),
VALUE_OR_RETURN(aidl2legacy_int32_t_product_strategy_t(aidl.id)));
}
// Keep in sync with android/media/audiopolicy/AudioProductStrategy#attributeMatches
-bool AudioProductStrategy::attributesMatches(const audio_attributes_t refAttributes,
- const audio_attributes_t clientAttritubes)
+int AudioProductStrategy::attributesMatchesScore(const audio_attributes_t refAttributes,
+ const audio_attributes_t clientAttritubes)
{
+ if (refAttributes == clientAttritubes) {
+ return MATCH_EQUALS;
+ }
if (refAttributes == AUDIO_ATTRIBUTES_INITIALIZER) {
// The default product strategy is the strategy that holds default attributes by convention.
// All attributes that fail to match will follow the default strategy for routing.
- // Choosing the default must be done as a fallback, the attributes match shall not
- // select the default.
- return false;
+ // Choosing the default must be done as a fallback,so return a default (zero) score to
+ // allow identify the fallback.
+ return MATCH_ON_DEFAULT_SCORE;
}
- return ((refAttributes.usage == AUDIO_USAGE_UNKNOWN) ||
- (clientAttritubes.usage == refAttributes.usage)) &&
- ((refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) ||
- (clientAttritubes.content_type == refAttributes.content_type)) &&
- ((refAttributes.flags == AUDIO_FLAG_NONE) ||
- (clientAttritubes.flags != AUDIO_FLAG_NONE &&
- (clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) &&
- ((strlen(refAttributes.tags) == 0) ||
- (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0));
+ int score = MATCH_ON_DEFAULT_SCORE;
+ if (refAttributes.usage == AUDIO_USAGE_UNKNOWN) {
+ score |= MATCH_ON_DEFAULT_SCORE;
+ } else if (clientAttritubes.usage == refAttributes.usage) {
+ score |= MATCH_ON_USAGE_SCORE;
+ } else {
+ return NO_MATCH;
+ }
+ if (refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) {
+ score |= MATCH_ON_DEFAULT_SCORE;
+ } else if (clientAttritubes.content_type == refAttributes.content_type) {
+ score |= MATCH_ON_CONTENT_TYPE_SCORE;
+ } else {
+ return NO_MATCH;
+ }
+ if (strlen(refAttributes.tags) == 0) {
+ score |= MATCH_ON_DEFAULT_SCORE;
+ } else if (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0) {
+ score |= MATCH_ON_TAGS_SCORE;
+ } else {
+ return NO_MATCH;
+ }
+ if (refAttributes.flags == AUDIO_FLAG_NONE) {
+ score |= MATCH_ON_DEFAULT_SCORE;
+ } else if ((clientAttritubes.flags != AUDIO_FLAG_NONE)
+ && ((clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) {
+ score |= MATCH_ON_FLAGS_SCORE;
+ } else {
+ return NO_MATCH;
+ }
+ return score;
}
} // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 7c7b65b..d58181c 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -81,7 +81,7 @@
// Binder for the AudioFlinger service that's passed to this client process from the system server.
// This allows specific isolated processes to access the audio system. Currently used only for the
// HotwordDetectionService.
-sp<IBinder> gAudioFlingerBinder = nullptr;
+static sp<IBinder> gAudioFlingerBinder = nullptr;
void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
@@ -97,6 +97,15 @@
gAudioFlingerBinder = audioFlinger;
}
+static sp<IAudioFlinger> gLocalAudioFlinger; // set if we are local.
+
+status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) {
+ Mutex::Autolock _l(gLock);
+ if (gAudioFlinger != nullptr) return INVALID_OPERATION;
+ gLocalAudioFlinger = af;
+ return OK;
+}
+
// establish binder interface to AudioFlinger service
const sp<IAudioFlinger> AudioSystem::get_audio_flinger() {
sp<IAudioFlinger> af;
@@ -104,7 +113,19 @@
bool reportNoError = false;
{
Mutex::Autolock _l(gLock);
- if (gAudioFlinger == 0) {
+ if (gAudioFlinger != nullptr) {
+ return gAudioFlinger;
+ }
+
+ if (gAudioFlingerClient == nullptr) {
+ gAudioFlingerClient = sp<AudioFlingerClient>::make();
+ } else {
+ reportNoError = true;
+ }
+
+ if (gLocalAudioFlinger != nullptr) {
+ gAudioFlinger = gLocalAudioFlinger;
+ } else {
sp<IBinder> binder;
if (gAudioFlingerBinder != nullptr) {
binder = gAudioFlingerBinder;
@@ -112,32 +133,24 @@
sp<IServiceManager> sm = defaultServiceManager();
do {
binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
- if (binder != 0)
- break;
+ if (binder != nullptr) break;
ALOGW("AudioFlinger not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
}
- if (gAudioFlingerClient == NULL) {
- gAudioFlingerClient = new AudioFlingerClient();
- } else {
- reportNoError = true;
- }
binder->linkToDeath(gAudioFlingerClient);
- gAudioFlinger = new AudioFlingerClientAdapter(
- interface_cast<media::IAudioFlingerService>(binder));
- LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
- afc = gAudioFlingerClient;
- // Make sure callbacks can be received by gAudioFlingerClient
- ProcessState::self()->startThreadPool();
+ const auto afs = interface_cast<media::IAudioFlingerService>(binder);
+ LOG_ALWAYS_FATAL_IF(afs == nullptr);
+ gAudioFlinger = sp<AudioFlingerClientAdapter>::make(afs);
}
+ afc = gAudioFlingerClient;
af = gAudioFlinger;
+ // Make sure callbacks can be received by gAudioFlingerClient
+ ProcessState::self()->startThreadPool();
}
- if (afc != 0) {
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- af->registerClient(afc);
- IPCThreadState::self()->restoreCallingIdentity(token);
- }
+ const int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ af->registerClient(afc);
+ IPCThreadState::self()->restoreCallingIdentity(token);
if (reportNoError) reportError(NO_ERROR);
return af;
}
@@ -1051,8 +1064,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
AudioConfig configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
@@ -1144,8 +1157,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
int32_t inputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(*input));
int32_t riidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_unique_id_t_int32_t(riid));
int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
@@ -1261,8 +1274,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
int32_t indexAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(index));
AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
@@ -1276,8 +1289,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
int32_t indexAidl;
@@ -1291,8 +1304,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
int32_t indexAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->getMaxVolumeIndexForAttributes(attrAidl, &indexAidl)));
@@ -1304,8 +1317,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
int32_t indexAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->getMinVolumeIndexForAttributes(attrAidl, &indexAidl)));
@@ -1328,7 +1341,7 @@
return result.value_or(PRODUCT_STRATEGY_NONE);
}
-status_t AudioSystem::getDevicesForAttributes(const AudioAttributes& aa,
+status_t AudioSystem::getDevicesForAttributes(const audio_attributes_t& aa,
AudioDeviceTypeAddrVector* devices,
bool forVolume) {
if (devices == nullptr) {
@@ -1337,8 +1350,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesEx aaAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioAttributes_AudioAttributesEx(aa));
+ media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(aa));
std::vector<AudioDevice> retAidl;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(aps->getDevicesForAttributes(aaAidl, forVolume, &retAidl)));
@@ -1856,8 +1869,8 @@
media::AudioPortConfigFw sourceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_config_AudioPortConfigFw(*source));
- media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attributes));
+ media::audio::common::AudioAttributes attributesAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attributes));
int32_t portIdAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->startAudioSource(sourceAidl, attributesAidl, &portIdAidl)));
@@ -2094,7 +2107,7 @@
AudioProductStrategyVector strategies;
listAudioProductStrategies(strategies);
for (const auto& strategy : strategies) {
- auto attrVect = strategy.getAudioAttributes();
+ auto attrVect = strategy.getVolumeGroupAttributes();
auto iter = std::find_if(begin(attrVect), end(attrVect), [&stream](const auto& attributes) {
return attributes.getStreamType() == stream;
});
@@ -2108,7 +2121,7 @@
audio_stream_type_t AudioSystem::attributesToStreamType(const audio_attributes_t& attr) {
product_strategy_t psId;
- status_t ret = AudioSystem::getProductStrategyFromAudioAttributes(AudioAttributes(attr), psId);
+ status_t ret = AudioSystem::getProductStrategyFromAudioAttributes(attr, psId);
if (ret != NO_ERROR) {
ALOGE("no strategy found for attributes %s", toString(attr).c_str());
return AUDIO_STREAM_MUSIC;
@@ -2117,10 +2130,9 @@
listAudioProductStrategies(strategies);
for (const auto& strategy : strategies) {
if (strategy.getId() == psId) {
- auto attrVect = strategy.getAudioAttributes();
+ auto attrVect = strategy.getVolumeGroupAttributes();
auto iter = std::find_if(begin(attrVect), end(attrVect), [&attr](const auto& refAttr) {
- return AudioProductStrategy::attributesMatches(
- refAttr.getAttributes(), attr);
+ return refAttr.matchesScore(attr) > 0;
});
if (iter != end(attrVect)) {
return iter->getStreamType();
@@ -2138,14 +2150,14 @@
return AUDIO_STREAM_MUSIC;
}
-status_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes& aa,
+status_t AudioSystem::getProductStrategyFromAudioAttributes(const audio_attributes_t& aa,
product_strategy_t& productStrategy,
bool fallbackOnDefault) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesEx aaAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioAttributes_AudioAttributesEx(aa));
+ media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(aa));
int32_t productStrategyAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2168,14 +2180,14 @@
return OK;
}
-status_t AudioSystem::getVolumeGroupFromAudioAttributes(const AudioAttributes& aa,
+status_t AudioSystem::getVolumeGroupFromAudioAttributes(const audio_attributes_t &aa,
volume_group_t& volumeGroup,
bool fallbackOnDefault) {
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesEx aaAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioAttributes_AudioAttributesEx(aa));
+ media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(aa));
int32_t volumeGroupAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->getVolumeGroupFromAudioAttributes(aaAidl, fallbackOnDefault, &volumeGroupAidl)));
@@ -2363,8 +2375,8 @@
audio_attributes_t attributes = attr != nullptr ? *attr : AUDIO_ATTRIBUTES_INITIALIZER;
audio_config_t configuration = config != nullptr ? *config : AUDIO_CONFIG_INITIALIZER;
- std::optional<media::AudioAttributesInternal> attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
+ std::optional<media::audio::common::AudioAttributes> attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
std::optional<AudioConfig> configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(configuration, false /*isInput*/));
std::vector<AudioDevice> devicesAidl = VALUE_OR_RETURN_STATUS(
@@ -2387,8 +2399,8 @@
return PERMISSION_DENIED;
}
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
AudioConfig configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
@@ -2411,8 +2423,8 @@
return PERMISSION_DENIED;
}
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
std::vector<media::audio::common::AudioProfile> audioProfilesAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2467,6 +2479,14 @@
return af->supportsBluetoothVariableLatency(support);
}
+status_t AudioSystem::getAudioPolicyConfig(media::AudioPolicyConfig *config) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == nullptr) {
+ return PERMISSION_DENIED;
+ }
+ return af->getAudioPolicyConfig(config);
+}
+
class CaptureStateListenerImpl : public media::BnCaptureStateListener,
public IBinder::DeathRecipient {
public:
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 12f5013..5bf6b656 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -175,8 +175,8 @@
auto result = [&]() -> ConversionResult<bool> {
media::audio::common::AudioConfigBase configAidl = VALUE_OR_RETURN(
legacy2aidl_audio_config_base_t_AudioConfigBase(config, false /*isInput*/));
- media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
+ media::audio::common::AudioAttributes attributesAidl = VALUE_OR_RETURN(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
bool retAidl;
RETURN_IF_ERROR(aidl_utils::statusTFromBinderStatus(
aps->isDirectOutputSupported(configAidl, attributesAidl, &retAidl)));
diff --git a/media/libaudioclient/AudioVolumeGroup.cpp b/media/libaudioclient/AudioVolumeGroup.cpp
index ab95246..c4ca5b9 100644
--- a/media/libaudioclient/AudioVolumeGroup.cpp
+++ b/media/libaudioclient/AudioVolumeGroup.cpp
@@ -23,7 +23,6 @@
#include <media/AidlConversion.h>
#include <media/AudioVolumeGroup.h>
-#include <media/AudioAttributes.h>
#include <media/PolicyAidlConversion.h>
namespace android {
@@ -50,9 +49,9 @@
aidl.groupId = VALUE_OR_RETURN(legacy2aidl_volume_group_t_int32_t(legacy.getId()));
aidl.name = legacy.getName();
aidl.audioAttributes = VALUE_OR_RETURN(
- convertContainer<std::vector<media::AudioAttributesInternal>>(
+ convertContainer<std::vector<media::audio::common::AudioAttributes>>(
legacy.getAudioAttributes(),
- legacy2aidl_audio_attributes_t_AudioAttributesInternal));
+ legacy2aidl_audio_attributes_t_AudioAttributes));
aidl.streams = VALUE_OR_RETURN(
convertContainer<std::vector<AudioStreamType>>(legacy.getStreamTypes(),
legacy2aidl_audio_stream_type_t_AudioStreamType));
@@ -66,7 +65,7 @@
VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
VALUE_OR_RETURN(convertContainer<AttributesVector>(
aidl.audioAttributes,
- aidl2legacy_AudioAttributesInternal_audio_attributes_t)),
+ aidl2legacy_AudioAttributes_audio_attributes_t)),
VALUE_OR_RETURN(convertContainer<StreamTypeVector>(
aidl.streams,
aidl2legacy_AudioStreamType_audio_stream_type_t))
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 756597e..00ef0a4 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -56,7 +56,7 @@
ConversionResult<media::CreateTrackRequest> IAudioFlinger::CreateTrackInput::toAidl() const {
media::CreateTrackRequest aidl;
- aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributes(attr));
// Do not be mislead by 'Input'--this is an input to 'createTrack', which creates output tracks.
aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_t_AudioConfig(
config, false /*isInput*/));
@@ -77,7 +77,7 @@
ConversionResult<IAudioFlinger::CreateTrackInput>
IAudioFlinger::CreateTrackInput::fromAidl(const media::CreateTrackRequest& aidl) {
IAudioFlinger::CreateTrackInput legacy;
- legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+ legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributes_audio_attributes_t(aidl.attr));
// Do not be mislead by 'Input'--this is an input to 'createTrack', which creates output tracks.
legacy.config = VALUE_OR_RETURN(
aidl2legacy_AudioConfig_audio_config_t(aidl.config, false /*isInput*/));
@@ -144,7 +144,7 @@
ConversionResult<media::CreateRecordRequest>
IAudioFlinger::CreateRecordInput::toAidl() const {
media::CreateRecordRequest aidl;
- aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributes(attr));
aidl.config = VALUE_OR_RETURN(
legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/));
aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
@@ -165,7 +165,7 @@
const media::CreateRecordRequest& aidl) {
IAudioFlinger::CreateRecordInput legacy;
legacy.attr = VALUE_OR_RETURN(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+ aidl2legacy_AudioAttributes_audio_attributes_t(aidl.attr));
legacy.config = VALUE_OR_RETURN(
aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config, true /*isInput*/));
legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
@@ -866,6 +866,16 @@
return NO_ERROR;
}
+status_t AudioFlingerClientAdapter::getAudioPolicyConfig(media::AudioPolicyConfig *config) {
+ if (config == nullptr) {
+ return BAD_VALUE;
+ }
+
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getAudioPolicyConfig(config)));
+
+ return NO_ERROR;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// AudioFlingerServerAdapter
AudioFlingerServerAdapter::AudioFlingerServerAdapter(
@@ -1399,4 +1409,8 @@
return Status::fromStatusT(mDelegate->supportsBluetoothVariableLatency(support));
}
+Status AudioFlingerServerAdapter::getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) {
+ return Status::fromStatusT(mDelegate->getAudioPolicyConfig(_aidl_return));
+}
+
} // namespace android
diff --git a/media/libaudioclient/AudioAttributes.cpp b/media/libaudioclient/VolumeGroupAttributes.cpp
similarity index 63%
rename from media/libaudioclient/AudioAttributes.cpp
rename to media/libaudioclient/VolumeGroupAttributes.cpp
index 260c06c..938e574 100644
--- a/media/libaudioclient/AudioAttributes.cpp
+++ b/media/libaudioclient/VolumeGroupAttributes.cpp
@@ -14,48 +14,53 @@
* limitations under the License.
*/
-#define LOG_TAG "AudioAttributes"
+#define LOG_TAG "VolumeGroupAttributes"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <media/AidlConversion.h>
-#include <media/AudioAttributes.h>
+#include <media/AudioProductStrategy.h>
+#include <media/VolumeGroupAttributes.h>
#include <media/PolicyAidlConversion.h>
namespace android {
-status_t AudioAttributes::readFromParcel(const Parcel* parcel) {
+int VolumeGroupAttributes::matchesScore(const audio_attributes_t &attributes) const {
+ return AudioProductStrategy::attributesMatchesScore(mAttributes, attributes);
+}
+
+status_t VolumeGroupAttributes::readFromParcel(const Parcel* parcel) {
media::AudioAttributesEx aidl;
RETURN_STATUS_IF_ERROR(aidl.readFromParcel(parcel));
- *this = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioAttributesEx_AudioAttributes(aidl));
+ *this = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(aidl));
return OK;
}
-status_t AudioAttributes::writeToParcel(Parcel* parcel) const {
+status_t VolumeGroupAttributes::writeToParcel(Parcel* parcel) const {
media::AudioAttributesEx aidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_AudioAttributes_AudioAttributesEx(*this));
+ legacy2aidl_VolumeGroupAttributes_AudioAttributesEx(*this));
return aidl.writeToParcel(parcel);
}
ConversionResult<media::AudioAttributesEx>
-legacy2aidl_AudioAttributes_AudioAttributesEx(const AudioAttributes& legacy) {
+legacy2aidl_VolumeGroupAttributes_AudioAttributesEx(const VolumeGroupAttributes& legacy) {
media::AudioAttributesEx aidl;
aidl.attributes = VALUE_OR_RETURN(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(legacy.getAttributes()));
+ legacy2aidl_audio_attributes_t_AudioAttributes(legacy.getAttributes()));
aidl.streamType = VALUE_OR_RETURN(
legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.getStreamType()));
aidl.groupId = VALUE_OR_RETURN(legacy2aidl_volume_group_t_int32_t(legacy.getGroupId()));
return aidl;
}
-ConversionResult<AudioAttributes>
-aidl2legacy_AudioAttributesEx_AudioAttributes(const media::AudioAttributesEx& aidl) {
- return AudioAttributes(VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
+ConversionResult<VolumeGroupAttributes>
+aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(const media::AudioAttributesEx& aidl) {
+ return VolumeGroupAttributes(VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
aidl.streamType)),
- VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(
+ VALUE_OR_RETURN(aidl2legacy_AudioAttributes_audio_attributes_t(
aidl.attributes)));
}
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
index 335866f..7827bdb 100644
--- a/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioStreamType;
/**
@@ -24,7 +24,7 @@
* {@hide}
*/
parcelable AudioAttributesEx {
- AudioAttributesInternal attributes;
+ AudioAttributes attributes;
AudioStreamType streamType;
/** Interpreted as volume_group_t. */
int groupId;
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
deleted file mode 100644
index 2e74206..0000000
--- a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 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.audio.common.AudioContentType;
-import android.media.audio.common.AudioSource;
-import android.media.audio.common.AudioUsage;
-
-/**
- * The "Internal" suffix of this type name is to disambiguate it from the
- * android.media.AudioAttributes SDK type.
- * {@hide}
- */
-parcelable AudioAttributesInternal {
- AudioContentType contentType;
- AudioUsage usage;
- AudioSource source;
- // Bitmask, indexed by AudioFlag.
- int flags;
- @utf8InCpp String tags; /* UTF8 */
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioFlag.aidl b/media/libaudioclient/aidl/android/media/AudioFlag.aidl
deleted file mode 100644
index acf4e6d..0000000
--- a/media/libaudioclient/aidl/android/media/AudioFlag.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioFlag {
- AUDIBILITY_ENFORCED = 0,
- SECURE = 1,
- SCO = 2,
- BEACON = 3,
- HW_AV_SYNC = 4,
- HW_HOTWORD = 5,
- BYPASS_INTERRUPTION_POLICY = 6,
- BYPASS_MUTE = 7,
- LOW_LATENCY = 8,
- DEEP_BUFFER = 9,
- NO_MEDIA_PROJECTION = 10,
- MUTE_HAPTIC = 11,
- NO_SYSTEM_CAPTURE = 12,
- CAPTURE_PRIVATE = 13,
- CONTENT_SPATIALIZED = 14,
- NEVER_SPATIALIZE = 15,
- CALL_REDIRECTION = 16,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioHwModule.aidl b/media/libaudioclient/aidl/android/media/AudioHwModule.aidl
new file mode 100644
index 0000000..9251400
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioHwModule.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 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.audio.common.AudioPort;
+import android.media.AudioRoute;
+
+/*
+ * A representation of a HAL module configuration.
+ * {@hide}
+ */
+parcelable AudioHwModule {
+ int /* audio_module_handle_t */ handle;
+ @utf8InCpp String name;
+ AudioPort[] ports;
+ AudioRoute[] routes;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl
new file mode 100644
index 0000000..87767c2
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2023 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.AudioHwModule;
+import android.media.SurroundSoundConfig;
+import android.media.audio.common.AudioHalEngineConfig;
+import android.media.audio.common.AudioMode;
+
+/*
+ * Audio policy configuration. Functionally replaces the APM XML file.
+ * {@hide}
+ */
+parcelable AudioPolicyConfig {
+ AudioHwModule[] modules;
+ AudioMode[] supportedModes;
+ SurroundSoundConfig surroundSoundConfig;
+ AudioHalEngineConfig engineConfig;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
index b95a1d3..424f8b8 100644
--- a/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioStreamType;
/**
@@ -26,6 +26,6 @@
/** Interpreted as volume_group_t. */
int groupId;
@utf8InCpp String name;
- AudioAttributesInternal[] audioAttributes;
+ AudioAttributes[] audioAttributes;
AudioStreamType[] streams;
}
diff --git a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
index b938a3e..57e8f42 100644
--- a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
@@ -16,8 +16,8 @@
package android.media;
-import android.media.AudioAttributesInternal;
import android.media.AudioClient;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioConfigBase;
/**
@@ -28,7 +28,7 @@
* {@hide}
*/
parcelable CreateRecordRequest {
- AudioAttributesInternal attr;
+ AudioAttributes attr;
AudioConfigBase config;
AudioClient clientInfo;
/** Interpreted as audio_unique_id_t. */
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
index 212221e..24e6a6c 100644
--- a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
import android.media.AudioClient;
import android.media.IAudioTrackCallback;
import android.media.SharedFileRegion;
@@ -30,7 +30,7 @@
* {@hide}
*/
parcelable CreateTrackRequest {
- AudioAttributesInternal attr;
+ AudioAttributes attr;
AudioConfig config;
AudioClient clientInfo;
@nullable SharedFileRegion sharedBuffer;
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index b722d14..1f4b3a9 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -17,6 +17,7 @@
package android.media;
import android.media.AudioPatchFw;
+import android.media.AudioPolicyConfig;
import android.media.AudioPortFw;
import android.media.AudioPortConfigFw;
import android.media.AudioUniqueIdUse;
@@ -270,6 +271,12 @@
*/
boolean isBluetoothVariableLatencyEnabled();
+ /**
+ * Only implemented for AIDL. Provides the APM configuration which
+ * used to be in the XML file.
+ */
+ AudioPolicyConfig getAudioPolicyConfig();
+
// When adding a new method, please review and update
// IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
// AudioFlinger.cpp AudioFlinger::onTransactWrapper()
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index fb87042..5c1a92f 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -18,8 +18,6 @@
import android.content.AttributionSourceState;
-import android.media.AudioAttributesEx;
-import android.media.AudioAttributesInternal;
import android.media.AudioDirectMode;
import android.media.AudioMix;
import android.media.AudioOffloadMode;
@@ -42,6 +40,7 @@
import android.media.ICaptureStateListener;
import android.media.INativeSpatializerCallback;
import android.media.SoundTriggerSession;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioConfig;
import android.media.audio.common.AudioConfigBase;
import android.media.audio.common.AudioDevice;
@@ -84,7 +83,7 @@
int /* audio_io_handle_t */ getOutput(AudioStreamType stream);
- GetOutputForAttrResponse getOutputForAttr(in AudioAttributesInternal attr,
+ GetOutputForAttrResponse getOutputForAttr(in AudioAttributes attr,
int /* audio_session_t */ session,
in AttributionSourceState attributionSource,
in AudioConfig config,
@@ -97,7 +96,7 @@
void releaseOutput(int /* audio_port_handle_t */ portId);
- GetInputForAttrResponse getInputForAttr(in AudioAttributesInternal attr,
+ GetInputForAttrResponse getInputForAttr(in AudioAttributes attr,
int /* audio_io_handle_t */ input,
int /* audio_unique_id_t */ riid,
int /* audio_session_t */ session,
@@ -124,20 +123,20 @@
int getStreamVolumeIndex(AudioStreamType stream,
in AudioDeviceDescription device);
- void setVolumeIndexForAttributes(in AudioAttributesInternal attr,
+ void setVolumeIndexForAttributes(in AudioAttributes attr,
in AudioDeviceDescription device,
int index);
- int getVolumeIndexForAttributes(in AudioAttributesInternal attr,
+ int getVolumeIndexForAttributes(in AudioAttributes attr,
in AudioDeviceDescription device);
- int getMaxVolumeIndexForAttributes(in AudioAttributesInternal attr);
+ int getMaxVolumeIndexForAttributes(in AudioAttributes attr);
- int getMinVolumeIndexForAttributes(in AudioAttributesInternal attr);
+ int getMinVolumeIndexForAttributes(in AudioAttributes attr);
int /* product_strategy_t */ getStrategyForStream(AudioStreamType stream);
- AudioDevice[] getDevicesForAttributes(in AudioAttributesEx attr, boolean forVolume);
+ AudioDevice[] getDevicesForAttributes(in AudioAttributes attr, boolean forVolume);
int /* audio_io_handle_t */ getOutputForEffect(in EffectDescriptor desc);
@@ -199,7 +198,7 @@
* Check if direct playback is possible for given format, sample rate, channel mask and flags.
*/
boolean isDirectOutputSupported(in AudioConfigBase config,
- in AudioAttributesInternal attributes);
+ in AudioAttributes attributes);
/**
* List currently attached audio ports and their attributes. Returns the generation.
@@ -271,7 +270,7 @@
void removeUserIdDeviceAffinities(int userId);
int /* audio_port_handle_t */ startAudioSource(in AudioPortConfigFw source,
- in AudioAttributesInternal attributes);
+ in AudioAttributes attributes);
void stopAudioSource(int /* audio_port_handle_t */ portId);
@@ -322,11 +321,11 @@
boolean isUltrasoundSupported();
AudioProductStrategy[] listAudioProductStrategies();
- int /* product_strategy_t */ getProductStrategyFromAudioAttributes(in AudioAttributesEx aa,
- boolean fallbackOnDefault);
+ int /* product_strategy_t */ getProductStrategyFromAudioAttributes(
+ in AudioAttributes aa, boolean fallbackOnDefault);
AudioVolumeGroup[] listAudioVolumeGroups();
- int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributesEx aa,
+ int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributes aa,
boolean fallbackOnDefault);
void setRttEnabled(boolean enabled);
@@ -384,21 +383,21 @@
* supported criteria. For instance, supplying no argument will tell if spatialization is
* supported or not in general.
*/
- boolean canBeSpatialized(in @nullable AudioAttributesInternal attr,
+ boolean canBeSpatialized(in @nullable AudioAttributes attr,
in @nullable AudioConfig config,
in AudioDevice[] devices);
/**
* Query how the direct playback is currently supported on the device.
*/
- AudioDirectMode getDirectPlaybackSupport(in AudioAttributesInternal attr,
+ AudioDirectMode getDirectPlaybackSupport(in AudioAttributes attr,
in AudioConfig config);
/**
* Query audio profiles available for direct playback on the current output device(s)
* for the specified audio attributes.
*/
- AudioProfile[] getDirectProfilesForAttributes(in AudioAttributesInternal attr);
+ AudioProfile[] getDirectProfilesForAttributes(in AudioAttributes attr);
// When adding a new method, please review and update
// AudioPolicyService.cpp AudioPolicyService::onTransact()
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 5bd0114..10f6d4a 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -21,10 +21,8 @@
#include <system/audio.h>
-#include <android/media/AudioAttributesInternal.h>
#include <android/media/AudioClient.h>
#include <android/media/AudioDirectMode.h>
-#include <android/media/AudioFlag.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
#include <android/media/AudioPortFw.h>
@@ -72,11 +70,6 @@
media::audio::common::AudioPortDeviceExt* aidl,
media::AudioPortDeviceExtSys* aidlDeviceExt);
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
- media::audio::common::AudioStreamType aidl);
-ConversionResult<media::audio::common::AudioStreamType>
-legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
-
ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
const media::AudioPortMixExtSys& aidlMixExt);
@@ -110,21 +103,6 @@
ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
const AudioClient& legacy);
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
-ConversionResult<media::AudioFlag>
-legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
-
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
-
-ConversionResult<audio_attributes_t>
-aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl);
-ConversionResult<media::AudioAttributesInternal>
-legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
ConversionResult<media::SharedFileRegion>
diff --git a/media/libaudioclient/include/media/AudioProductStrategy.h b/media/libaudioclient/include/media/AudioProductStrategy.h
index b55b506..fcbb019 100644
--- a/media/libaudioclient/include/media/AudioProductStrategy.h
+++ b/media/libaudioclient/include/media/AudioProductStrategy.h
@@ -20,7 +20,7 @@
#include <android/media/AudioProductStrategy.h>
#include <media/AidlConversionUtil.h>
#include <media/AudioCommonTypes.h>
-#include <media/AudioAttributes.h>
+#include <media/VolumeGroupAttributes.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <binder/Parcelable.h>
@@ -31,34 +31,53 @@
{
public:
AudioProductStrategy() {}
- AudioProductStrategy(const std::string &name, const std::vector<AudioAttributes> &attributes,
+ AudioProductStrategy(const std::string &name,
+ const std::vector<VolumeGroupAttributes> &attributes,
product_strategy_t id) :
- mName(name), mAudioAttributes(attributes), mId(id) {}
+ mName(name), mVolumeGroupAttributes(attributes), mId(id) {}
const std::string &getName() const { return mName; }
- std::vector<AudioAttributes> getAudioAttributes() const { return mAudioAttributes; }
+ std::vector<VolumeGroupAttributes> getVolumeGroupAttributes() const {
+ return mVolumeGroupAttributes;
+ }
product_strategy_t getId() const { return mId; }
status_t readFromParcel(const Parcel *parcel) override;
status_t writeToParcel(Parcel *parcel) const override;
/**
- * @brief attributesMatches: checks if client attributes matches with a reference attributes
- * "matching" means the usage shall match if reference attributes has a defined usage, AND
- * content type shall match if reference attributes has a defined content type AND
+ * @brief attributesMatchesScore: checks if client attributes matches with a reference
+ * attributes "matching" means the usage shall match if reference attributes has a defined
+ * usage, AND content type shall match if reference attributes has a defined content type AND
* flags shall match if reference attributes has defined flags AND
* tags shall match if reference attributes has defined tags.
- * Reference attributes "default" shall not be considered as a "true" case. This convention
+ * Reference attributes "default" shall be considered as a weak match case. This convention
* is used to identify the default strategy.
* @param refAttributes to be considered
* @param clientAttritubes to be considered
- * @return true if matching, false otherwise
+ * @return {@code INVALID_SCORE} if not matching, {@code MATCH_ON_DEFAULT_SCORE} if matching
+ * to default strategy, non zero positive score if matching a strategy.
*/
+ static int attributesMatchesScore(const audio_attributes_t refAttributes,
+ const audio_attributes_t clientAttritubes);
+
static bool attributesMatches(const audio_attributes_t refAttributes,
- const audio_attributes_t clientAttritubes);
+ const audio_attributes_t clientAttritubes) {
+ return attributesMatchesScore(refAttributes, clientAttritubes) > 0;
+ }
+
+ static const int MATCH_ON_TAGS_SCORE = 1 << 3;
+ static const int MATCH_ON_FLAGS_SCORE = 1 << 2;
+ static const int MATCH_ON_USAGE_SCORE = 1 << 1;
+ static const int MATCH_ON_CONTENT_TYPE_SCORE = 1 << 0;
+ static const int MATCH_ON_DEFAULT_SCORE = 0;
+ static const int MATCH_EQUALS = MATCH_ON_TAGS_SCORE | MATCH_ON_FLAGS_SCORE
+ | MATCH_ON_USAGE_SCORE | MATCH_ON_CONTENT_TYPE_SCORE;
+ static const int NO_MATCH = -1;
+
private:
std::string mName;
- std::vector<AudioAttributes> mAudioAttributes;
+ std::vector<VolumeGroupAttributes> mVolumeGroupAttributes;
product_strategy_t mId;
};
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 3e3b79c..25111d7 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,6 +23,7 @@
#include <vector>
#include <android/content/AttributionSourceState.h>
+#include <android/media/AudioPolicyConfig.h>
#include <android/media/AudioPortFw.h>
#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnAudioFlingerClient.h>
@@ -166,6 +167,10 @@
// HotwordDetectionService.
static void setAudioFlingerBinder(const sp<IBinder>& audioFlinger);
+ // Sets a local AudioFlinger interface to be used by AudioSystem.
+ // This is used by audioserver main() to avoid binder AIDL translation.
+ static status_t setLocalAudioFlinger(const sp<IAudioFlinger>& af);
+
// helper function to obtain AudioFlinger service handle
static const sp<IAudioFlinger> get_audio_flinger();
@@ -335,7 +340,7 @@
static status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
static product_strategy_t getStrategyForStream(audio_stream_type_t stream);
- static status_t getDevicesForAttributes(const AudioAttributes &aa,
+ static status_t getDevicesForAttributes(const audio_attributes_t &aa,
AudioDeviceTypeAddrVector *devices,
bool forVolume);
@@ -462,7 +467,7 @@
static status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
static status_t getProductStrategyFromAudioAttributes(
- const AudioAttributes &aa, product_strategy_t &productStrategy,
+ const audio_attributes_t &aa, product_strategy_t &productStrategy,
bool fallbackOnDefault = true);
static audio_attributes_t streamTypeToAttributes(audio_stream_type_t stream);
@@ -471,7 +476,8 @@
static status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
static status_t getVolumeGroupFromAudioAttributes(
- const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault = true);
+ const audio_attributes_t &aa, volume_group_t &volumeGroup,
+ bool fallbackOnDefault = true);
static status_t setRttEnabled(bool enabled);
@@ -588,6 +594,8 @@
static status_t supportsBluetoothVariableLatency(bool *support);
+ static status_t getAudioPolicyConfig(media::AudioPolicyConfig *config);
+
// A listener for capture state changes.
class CaptureStateListener : public virtual RefBase {
public:
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c43769b..1064e59 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -374,6 +374,8 @@
virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
+
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) = 0;
};
/**
@@ -485,6 +487,7 @@
status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
status_t supportsBluetoothVariableLatency(bool* support) override;
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) override;
private:
const sp<media::IAudioFlingerService> mDelegate;
@@ -583,6 +586,8 @@
media::BnAudioFlingerService::TRANSACTION_isBluetoothVariableLatencyEnabled,
SUPPORTS_BLUETOOTH_VARIABLE_LATENCY =
media::BnAudioFlingerService::TRANSACTION_supportsBluetoothVariableLatency,
+ GET_AUDIO_POLICY_CONFIG =
+ media::BnAudioFlingerService::TRANSACTION_getAudioPolicyConfig,
};
protected:
@@ -713,6 +718,7 @@
Status setBluetoothVariableLatencyEnabled(bool enabled) override;
Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
Status supportsBluetoothVariableLatency(bool* support) override;
+ Status getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) override;
private:
const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
};
diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/VolumeGroupAttributes.h
similarity index 72%
rename from media/libaudioclient/include/media/AudioAttributes.h
rename to media/libaudioclient/include/media/VolumeGroupAttributes.h
index 24bd179..46b3612 100644
--- a/media/libaudioclient/include/media/AudioAttributes.h
+++ b/media/libaudioclient/include/media/VolumeGroupAttributes.h
@@ -26,15 +26,22 @@
namespace android {
-class AudioAttributes : public Parcelable
+class VolumeGroupAttributes : public Parcelable
{
public:
- AudioAttributes() = default;
- AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {} // NOLINT
- AudioAttributes(volume_group_t groupId,
+ VolumeGroupAttributes() = default;
+ VolumeGroupAttributes(const audio_attributes_t &attributes)
+ : mAttributes(attributes) {} // NOLINT
+ VolumeGroupAttributes(volume_group_t groupId,
audio_stream_type_t stream,
const audio_attributes_t &attributes) :
- mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {}
+ mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {
+ // TODO: align native & JAVA source initializer.
+ // As far as this class concerns attributes for volume group, it applies only to playback.
+ mAttributes.source = AUDIO_SOURCE_INVALID;
+ }
+
+ int matchesScore(const audio_attributes_t &attributes) const;
audio_attributes_t getAttributes() const { return mAttributes; }
@@ -61,8 +68,8 @@
// AIDL conversion routines.
ConversionResult<media::AudioAttributesEx>
-legacy2aidl_AudioAttributes_AudioAttributesEx(const AudioAttributes& legacy);
-ConversionResult<AudioAttributes>
-aidl2legacy_AudioAttributesEx_AudioAttributes(const media::AudioAttributesEx& aidl);
+legacy2aidl_VolumeGroupAttributes_AudioAttributesEx(const VolumeGroupAttributes& legacy);
+ConversionResult<VolumeGroupAttributes>
+aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(const media::AudioAttributesEx& aidl);
} // namespace android
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 91ef7b3..a7bb02a 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -94,6 +94,11 @@
AudioChannelLayout::LAYOUT_STEREO);
}
+AudioChannelLayout make_ACL_Tri() {
+ return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::LAYOUT_TRI);
+}
+
AudioChannelLayout make_ACL_LayoutArbitrary() {
return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
// Use channels that exist both for input and output,
@@ -311,8 +316,8 @@
AudioChannelLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
testing::Combine(
testing::Values(AudioChannelLayout{}, make_ACL_Invalid(), make_ACL_Stereo(),
- make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
- make_ACL_ChannelIndexArbitrary(),
+ make_ACL_Tri(), make_ACL_LayoutArbitrary(),
+ make_ACL_ChannelIndex2(), make_ACL_ChannelIndexArbitrary(),
AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
AudioChannelLayout::CHANNEL_FRONT_LEFT),
AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
diff --git a/media/libaudioclient/tests/audioclient_serialization_tests.cpp b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
index ef8500b..97b37da 100644
--- a/media/libaudioclient/tests/audioclient_serialization_tests.cpp
+++ b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
@@ -103,7 +103,7 @@
attr.usage = kUsages[rand() % kUsages.size()];
attr.source = kInputSources[rand() % kInputSources.size()];
// attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)]
- attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3fff);
+ attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3ffd); // exclude AUDIO_FLAG_SECURE
sprintf(attr.tags, "%s",
CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str());
}
@@ -119,32 +119,33 @@
TEST_F(SerializationTest, AudioProductStrategyBinderization) {
for (int j = 0; j < 512; j++) {
const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)};
- std::vector<AudioAttributes> audioattributesvector;
+ SCOPED_TRACE(name);
+ std::vector<VolumeGroupAttributes> volumeGroupAttrVector;
for (auto i = 0; i < 16; i++) {
audio_attributes_t attributes;
fillAudioAttributes(attributes);
- AudioAttributes audioattributes{static_cast<volume_group_t>(rand()),
- kStreamtypes[rand() % kStreamtypes.size()], attributes};
- audioattributesvector.push_back(audioattributes);
+ VolumeGroupAttributes volumeGroupAttr{static_cast<volume_group_t>(rand()),
+ kStreamtypes[rand() % kStreamtypes.size()],
+ attributes};
+ volumeGroupAttrVector.push_back(volumeGroupAttr);
}
product_strategy_t psId = static_cast<product_strategy_t>(rand());
- AudioProductStrategy aps{name, audioattributesvector, psId};
+ AudioProductStrategy aps{name, volumeGroupAttrVector, psId};
Parcel p;
- EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p)) << name;
+ EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p));
AudioProductStrategy apsCopy;
p.setDataPosition(0);
- EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p)) << name;
- EXPECT_EQ(apsCopy.getName(), name) << name;
- EXPECT_EQ(apsCopy.getId(), psId) << name;
- auto avec = apsCopy.getAudioAttributes();
- EXPECT_EQ(avec.size(), audioattributesvector.size()) << name;
- for (int i = 0; i < audioattributesvector.size(); i++) {
- EXPECT_EQ(avec[i].getGroupId(), audioattributesvector[i].getGroupId()) << name;
- EXPECT_EQ(avec[i].getStreamType(), audioattributesvector[i].getStreamType()) << name;
- EXPECT_TRUE(avec[i].getAttributes() == audioattributesvector[i].getAttributes())
- << name;
+ EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p));
+ EXPECT_EQ(apsCopy.getName(), name);
+ EXPECT_EQ(apsCopy.getId(), psId);
+ auto avec = apsCopy.getVolumeGroupAttributes();
+ EXPECT_EQ(avec.size(), volumeGroupAttrVector.size());
+ for (int i = 0; i < std::min(avec.size(), volumeGroupAttrVector.size()); i++) {
+ EXPECT_EQ(avec[i].getGroupId(), volumeGroupAttrVector[i].getGroupId());
+ EXPECT_EQ(avec[i].getStreamType(), volumeGroupAttrVector[i].getStreamType());
+ EXPECT_TRUE(avec[i].getAttributes() == volumeGroupAttrVector[i].getAttributes());
}
}
}
@@ -293,17 +294,17 @@
audio_stream_type_t stream = mAudioStream;
audio_attributes_t attributes;
fillAudioAttributes(attributes);
- AudioAttributes audioattributes{groupId, stream, attributes};
+ VolumeGroupAttributes volumeGroupAttr{groupId, stream, attributes};
Parcel p;
- EXPECT_EQ(NO_ERROR, audioattributes.writeToParcel(&p)) << msg;
+ EXPECT_EQ(NO_ERROR, volumeGroupAttr.writeToParcel(&p)) << msg;
- AudioAttributes audioattributesCopy;
+ VolumeGroupAttributes volumeGroupAttrCopy;
p.setDataPosition(0);
- EXPECT_EQ(NO_ERROR, audioattributesCopy.readFromParcel(&p)) << msg;
- EXPECT_EQ(audioattributesCopy.getGroupId(), audioattributes.getGroupId()) << msg;
- EXPECT_EQ(audioattributesCopy.getStreamType(), audioattributes.getStreamType()) << msg;
- EXPECT_TRUE(audioattributesCopy.getAttributes() == attributes) << msg;
+ EXPECT_EQ(NO_ERROR, volumeGroupAttrCopy.readFromParcel(&p)) << msg;
+ EXPECT_EQ(volumeGroupAttrCopy.getGroupId(), volumeGroupAttr.getGroupId()) << msg;
+ EXPECT_EQ(volumeGroupAttrCopy.getStreamType(), volumeGroupAttr.getStreamType()) << msg;
+ EXPECT_TRUE(volumeGroupAttrCopy.getAttributes() == attributes) << msg;
}
// audioStream
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index d43b669..f31bd95 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -347,7 +347,7 @@
bool isPublicStrategy(const AudioProductStrategy& strategy) {
bool result = true;
- for (auto& attribute : strategy.getAudioAttributes()) {
+ for (auto& attribute : strategy.getVolumeGroupAttributes()) {
if (attribute.getAttributes() == AUDIO_ATTRIBUTES_INITIALIZER &&
(uint32_t(attribute.getStreamType()) >= AUDIO_STREAM_PUBLIC_CNT)) {
result = false;
@@ -386,7 +386,7 @@
for (const auto& strategy : strategies) {
if (!isPublicStrategy(strategy)) continue;
- for (const auto& att : strategy.getAudioAttributes()) {
+ for (const auto& att : strategy.getVolumeGroupAttributes()) {
if (strategy.attributesMatches(att.getAttributes(), attributes)) {
hasStrategyForMedia = true;
mediaStrategy = strategy;
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 30a4bf9..502bcc7 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -240,19 +240,46 @@
]
}
-cc_library_shared {
- name: "libaudiohal@aidl",
+cc_defaults {
+ name: "libaudiohal_aidl_default",
defaults: [
- "libaudiohal_default",
"latest_android_hardware_audio_common_ndk_shared",
"latest_android_hardware_audio_core_ndk_shared",
"latest_android_hardware_audio_effect_ndk_shared",
"latest_android_media_audio_common_types_ndk_shared",
],
+ shared_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudio_aidl_conversion_common_ndk_cpp",
+ "libaudio_aidl_conversion_core_ndk",
+ "libaudio_aidl_conversion_effect_ndk",
+ "libaudioaidlcommon",
+ "libbinder_ndk",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ "libeffectsconfig_headers",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_CPP_NDK",
+ ],
+}
+
+cc_library_shared {
+ name: "libaudiohal@aidl",
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_aidl_default",
+ ],
srcs: [
- "DeviceHalAidl.cpp",
"DevicesFactoryHalEntry.cpp",
- "DevicesFactoryHalAidl.cpp",
"EffectConversionHelperAidl.cpp",
"EffectBufferHalAidl.cpp",
"EffectHalAidl.cpp",
@@ -274,32 +301,17 @@
"effectsAidlConversion/AidlConversionVisualizer.cpp",
"EffectsFactoryHalAidl.cpp",
"EffectsFactoryHalEntry.cpp",
+ ":audio_effectproxy_src_files",
+ ":core_audio_hal_aidl_src_files",
+ ],
+}
+
+filegroup {
+ name: "core_audio_hal_aidl_src_files",
+ srcs: [
+ "DeviceHalAidl.cpp",
+ "DevicesFactoryHalAidl.cpp",
"StreamHalAidl.cpp",
- ":audio_effectproxy_src_files"
- ],
- static_libs: [
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
- ],
- shared_libs: [
- "libaudio_aidl_conversion_common_cpp",
- "libaudio_aidl_conversion_common_ndk",
- "libaudio_aidl_conversion_common_ndk_cpp",
- "libaudio_aidl_conversion_core_ndk",
- "libaudio_aidl_conversion_effect_ndk",
- "libaudioaidlcommon",
- "libbinder_ndk",
- ],
- header_libs: [
- "libaudio_system_headers",
- "libeffectsconfig_headers",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wthread-safety",
- "-DBACKEND_CPP_NDK",
],
}
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
index db6b6cf..5534d13 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -20,6 +20,9 @@
#include <string_view>
#include <vector>
+#include <android-base/expected.h>
+#include <error/Result.h>
+#include <media/AudioParameter.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -51,4 +54,24 @@
const std::string mClassName;
};
+// 'action' must accept a value of type 'T' and return 'status_t'.
+// The function returns 'true' if the parameter was found, and the action has succeeded.
+// The function returns 'false' if the parameter was not found.
+// Any errors get propagated, if there are errors it means the parameter was found.
+template<typename T, typename F>
+error::Result<bool> filterOutAndProcessParameter(
+ AudioParameter& parameters, const String8& key, const F& action) {
+ if (parameters.containsKey(key)) {
+ T value;
+ status_t status = parameters.get(key, value);
+ if (status == OK) {
+ parameters.remove(key);
+ status = action(value);
+ if (status == OK) return true;
+ }
+ return base::unexpected(status);
+ }
+ return false;
+}
+
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index e452a35..922604f 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -35,6 +35,7 @@
#include "StreamHalAidl.h"
using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::Boolean;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioConfig;
using aidl::android::media::audio::common::AudioDevice;
@@ -68,6 +69,9 @@
using aidl::android::hardware::audio::common::RecordTrackMetadata;
using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::AudioRoute;
+using aidl::android::hardware::audio::core::IBluetooth;
+using aidl::android::hardware::audio::core::IBluetoothA2dp;
+using aidl::android::hardware::audio::core::IBluetoothLe;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::ITelephony;
using aidl::android::hardware::audio::core::ModuleDebug;
@@ -107,14 +111,32 @@
return cpp;
}
+template<typename T>
+std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
+ ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
+ if (module != nullptr) {
+ std::shared_ptr<T> instance;
+ if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
+ return instance;
+ }
+ }
+ return nullptr;
+}
+
} // namespace
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
+ : ConversionHelperAidl("DeviceHalAidl"),
+ mInstance(instance), mModule(module),
+ mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
+ mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
+ mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
+ mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)) {
+}
+
status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
- auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
- return ndk2cpp_AudioPort(pair.second);
- };
- return ::aidl::android::convertRange(mPorts.begin(), mPorts.end(), ports->begin(),
- convertAudioPortFromMap);
+ return ::aidl::android::convertContainer(mPorts, ports,
+ [](const Ports::value_type& pair) { return ndk2cpp_AudioPort(pair.second); });
}
status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
@@ -124,6 +146,22 @@
return OK;
}
+status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
+ TIME_CHECK();
+ if (modes == nullptr) {
+ return BAD_VALUE;
+ }
+ if (mModule == nullptr) return NO_INIT;
+ if (mTelephony == nullptr) return INVALID_OPERATION;
+ std::vector<AudioMode> aidlModes;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
+ *modes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
+ aidlModes, ndk2cpp_AudioMode));
+ return OK;
+}
+
status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
@@ -175,17 +213,14 @@
status_t DeviceHalAidl::setVoiceVolume(float volume) {
TIME_CHECK();
if (!mModule) return NO_INIT;
- std::shared_ptr<ITelephony> telephony;
- if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
- status.isOk() && telephony != nullptr) {
- ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
- RETURN_STATUS_IF_ERROR(
- statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
- ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
- "%s: the resulting voice volume %f is not the same as requested %f",
- __func__, outConfig.voiceVolume.value().value, volume);
- }
- return INVALID_OPERATION;
+ if (mTelephony == nullptr) return INVALID_OPERATION;
+ ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
+ ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
+ "%s: the resulting voice volume %f is not the same as requested %f",
+ __func__, outConfig.voiceVolume.value().value, volume);
+ return OK;
}
status_t DeviceHalAidl::setMasterVolume(float volume) {
@@ -204,10 +239,8 @@
TIME_CHECK();
if (!mModule) return NO_INIT;
AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
- std::shared_ptr<ITelephony> telephony;
- if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
- status.isOk() && telephony != nullptr) {
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
+ if (mTelephony != nullptr) {
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
}
return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
}
@@ -236,15 +269,32 @@
return statusTFromBinderStatus(mModule->getMasterMute(state));
}
-status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
- TIME_CHECK();
+status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ AudioParameter parameters(kvPairs);
+ ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
+
+ if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
+ ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
+ }
+ if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
+ ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
+ }
+ if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
+ ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
+ }
+ if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
+ ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
+ }
+
+ ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"",
+ __func__, parameters.toString().c_str());
return OK;
}
status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
TIME_CHECK();
+ // FIXME(b/278976019): Support keyReconfigA2dpSupported via vendor plugin
values->clear();
if (!mModule) return NO_INIT;
ALOGE("%s not implemented yet", __func__);
@@ -1040,6 +1090,150 @@
return OK;
}
+status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶meters) {
+ TIME_CHECK();
+ std::optional<bool> a2dpEnabled;
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtA2dpSuspended),
+ [&a2dpEnabled](const String8& trueOrFalse) {
+ if (trueOrFalse == AudioParameter::valueTrue) {
+ a2dpEnabled = false; // 'suspended' == true
+ return OK;
+ } else if (trueOrFalse == AudioParameter::valueFalse) {
+ a2dpEnabled = true; // 'suspended' == false
+ return OK;
+ }
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
+ return BAD_VALUE;
+ }));
+ // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin
+ if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
+ return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
+ }
+ return OK;
+}
+
+status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter ¶meters) {
+ TIME_CHECK();
+ IBluetooth::HfpConfig hfpConfig;
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtHfpEnable),
+ [&hfpConfig](const String8& trueOrFalse) {
+ if (trueOrFalse == AudioParameter::valueTrue) {
+ hfpConfig.isEnabled = Boolean{ .value = true };
+ return OK;
+ } else if (trueOrFalse == AudioParameter::valueFalse) {
+ hfpConfig.isEnabled = Boolean{ .value = false };
+ return OK;
+ }
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
+ return BAD_VALUE;
+ }));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyBtHfpSamplingRate),
+ [&hfpConfig](int sampleRate) {
+ return sampleRate > 0 ?
+ hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
+ }));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+ parameters, String8(AudioParameter::keyBtHfpVolume),
+ [&hfpConfig](int volume0to15) {
+ if (volume0to15 >= 0 && volume0to15 <= 15) {
+ hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
+ return OK;
+ }
+ return BAD_VALUE;
+ }));
+ if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
+ IBluetooth::HfpConfig newHfpConfig;
+ return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
+ }
+ return OK;
+}
+
+status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter ¶meters) {
+ TIME_CHECK();
+ std::optional<bool> leEnabled;
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtLeSuspended),
+ [&leEnabled](const String8& trueOrFalse) {
+ if (trueOrFalse == AudioParameter::valueTrue) {
+ leEnabled = false; // 'suspended' == true
+ return OK;
+ } else if (trueOrFalse == AudioParameter::valueFalse) {
+ leEnabled = true; // 'suspended' == false
+ return OK;
+ }
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
+ return BAD_VALUE;
+ }));
+ if (mBluetoothLe != nullptr && leEnabled.has_value()) {
+ return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
+ }
+ return OK;
+}
+
+status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter ¶meters) {
+ TIME_CHECK();
+ IBluetooth::ScoConfig scoConfig;
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtSco),
+ [&scoConfig](const String8& onOrOff) {
+ if (onOrOff == AudioParameter::valueOn) {
+ scoConfig.isEnabled = Boolean{ .value = true };
+ return OK;
+ } else if (onOrOff == AudioParameter::valueOff) {
+ scoConfig.isEnabled = Boolean{ .value = false };
+ return OK;
+ }
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyBtSco, onOrOff.c_str());
+ return BAD_VALUE;
+ }));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtScoHeadsetName),
+ [&scoConfig](const String8& name) {
+ scoConfig.debugName = name;
+ return OK;
+ }));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtNrec),
+ [&scoConfig](const String8& onOrOff) {
+ if (onOrOff == AudioParameter::valueOn) {
+ scoConfig.isNrecEnabled = Boolean{ .value = true };
+ return OK;
+ } else if (onOrOff == AudioParameter::valueOff) {
+ scoConfig.isNrecEnabled = Boolean{ .value = false };
+ return OK;
+ }
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyBtNrec, onOrOff.c_str());
+ return BAD_VALUE;
+ }));
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyBtScoWb),
+ [&scoConfig](const String8& onOrOff) {
+ if (onOrOff == AudioParameter::valueOn) {
+ scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
+ return OK;
+ } else if (onOrOff == AudioParameter::valueOff) {
+ scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
+ return OK;
+ }
+ ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+ AudioParameter::keyBtScoWb, onOrOff.c_str());
+ return BAD_VALUE;
+ }));
+ if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
+ IBluetooth::ScoConfig newScoConfig;
+ return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
+ }
+ return OK;
+}
+
status_t DeviceHalAidl::findOrCreatePatch(
const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index ea3e125..e29ae79 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -72,6 +72,8 @@
status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+ status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) override;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
@@ -197,8 +199,7 @@
// Must not be constructed directly by clients.
DeviceHalAidl(
const std::string& instance,
- const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
- : ConversionHelperAidl("DeviceHalAidl"), mInstance(instance), mModule(module) {}
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module);
~DeviceHalAidl() override = default;
@@ -209,6 +210,10 @@
status_t createOrUpdatePortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
PortConfigs::iterator* result, bool *created);
+ status_t filterAndUpdateBtA2dpParameters(AudioParameter ¶meters);
+ status_t filterAndUpdateBtHfpParameters(AudioParameter ¶meters);
+ status_t filterAndUpdateBtLeParameters(AudioParameter ¶meters);
+ status_t filterAndUpdateBtScoParameters(AudioParameter ¶meters);
status_t findOrCreatePatch(
const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds,
@@ -282,6 +287,10 @@
const std::string mInstance;
const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> mTelephony;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth> mBluetooth;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp> mBluetoothA2dp;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe> mBluetoothLe;
Ports mPorts;
int32_t mDefaultInputPortId = -1;
int32_t mDefaultOutputPortId = -1;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index ad9e182..cd83171 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -88,6 +88,11 @@
return INVALID_OPERATION;
}
+status_t DeviceHalHidl::getSupportedModes(
+ std::vector<media::audio::common::AudioMode> *modes __unused) {
+ return INVALID_OPERATION;
+}
+
status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 6b6c197..17acd2f 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -33,6 +33,8 @@
status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+ status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) override;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 8345cd2..c8cce96 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -83,24 +83,15 @@
if (name == nullptr || device == nullptr) {
return BAD_VALUE;
}
-
- // FIXME: Remove this call and the check for the supported module names
- // after implementing retrieval of module names on the framework side.
- // Currently it is still using the legacy XML config.
- std::vector<std::string> deviceNames;
- if (status_t status = getDeviceNames(&deviceNames); status != OK) {
- return status;
- }
std::shared_ptr<IModule> service;
- if (std::find(deviceNames.begin(), deviceNames.end(), name) != deviceNames.end()) {
- if (strcmp(name, "primary") == 0) name = "default";
- auto serviceName = std::string(IModule::descriptor) + "/" + name;
- service = IModule::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
- ALOGE_IF(service == nullptr, "%s fromBinder %s failed", __func__, serviceName.c_str());
+ if (strcmp(name, "primary") == 0) name = "default";
+ auto serviceName = std::string(IModule::descriptor) + "/" + name;
+ service = IModule::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+ if (service == nullptr) {
+ ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
+ return NO_INIT;
}
- // If the service is a nullptr, the device object will not be really functional,
- // but will not crash either.
*device = sp<DeviceHalAidl>::make(name, service);
return OK;
}
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index b61532d..3bb045b 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -20,6 +20,7 @@
//#define LOG_NDEBUG 0
#include <fmq/AidlMessageQueue.h>
+#include <system/audio_aidl_utils.h>
#include <utils/Log.h>
#include "EffectProxy.h"
@@ -32,6 +33,7 @@
using ::aidl::android::hardware::audio::effect::Parameter;
using ::aidl::android::hardware::audio::effect::State;
using ::aidl::android::media::audio::common::AudioUuid;
+using ::android::audio::utils::toString;
namespace android {
namespace effect {
@@ -54,7 +56,7 @@
// sub effect must have same proxy UUID as EffectProxy, and the type UUID must match.
ndk::ScopedAStatus EffectProxy::addSubEffect(const Descriptor& sub) {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
if (0 != mSubEffects.count(sub.common.id) || !sub.common.id.proxy.has_value() ||
sub.common.id.proxy.value() != mIdentity.uuid) {
ALOGE("%s sub effect already exist or mismatch %s", __func__, sub.toString().c_str());
@@ -92,15 +94,15 @@
}
ndk::ScopedAStatus EffectProxy::create() {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
for (auto& sub : mSubEffects) {
auto& effectHandle = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- ALOGI("%s sub-effect %s", __func__, sub.first.uuid.toString().c_str());
+ ALOGI("%s sub-effect %s", __func__, toString(sub.first.uuid).c_str());
status = mFactory->createEffect(sub.first.uuid, &effectHandle);
if (!status.isOk() || !effectHandle) {
- ALOGE("%s sub-effect failed %s", __func__, sub.first.uuid.toString().c_str());
+ ALOGE("%s sub-effect failed %s", __func__, toString(sub.first.uuid).c_str());
break;
}
}
@@ -113,7 +115,7 @@
}
ndk::ScopedAStatus EffectProxy::destroy() {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
if (status.isOk()) {
@@ -131,7 +133,7 @@
const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) {
const auto& desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(sub.second);
ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload,
- desc.common.id.uuid.toString().c_str(), desc.common.flags.toString().c_str());
+ toString(desc.common.id.uuid).c_str(), desc.common.flags.toString().c_str());
return offload->isOffload ==
(desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL);
});
@@ -143,7 +145,7 @@
mActiveSub = itor->first;
ALOGI("%s: active %soffload sub-effect: %s, flags %s", __func__,
- offload->isOffload ? "" : "non-", mActiveSub.uuid.toString().c_str(),
+ offload->isOffload ? "" : "non-", toString(mActiveSub.uuid).c_str(),
std::get<SubEffectTupleIndex::DESCRIPTOR>(itor->second).common.flags.toString().c_str());
return ndk::ScopedAStatus::ok();
}
@@ -152,14 +154,14 @@
ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
IEffect::OpenEffectReturn* ret __unused) {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
for (auto& sub : mSubEffects) {
auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
auto& openRet = std::get<SubEffectTupleIndex::RETURN>(sub.second);
if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) {
- ALOGE("%s: failed to open UUID %s", __func__, sub.first.uuid.toString().c_str());
+ ALOGE("%s: failed to open UUID %s", __func__, toString(sub.first.uuid).c_str());
break;
}
}
@@ -173,7 +175,7 @@
}
ndk::ScopedAStatus EffectProxy::close() {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
return effect->close();
});
@@ -203,7 +205,7 @@
// Handle with active sub-effect first, only send to other sub-effects when success
ndk::ScopedAStatus EffectProxy::command(CommandId id) {
- ALOGV("%s: %s, command %s", __func__, mIdentity.type.toString().c_str(),
+ ALOGV("%s: %s, command %s", __func__, toString(mIdentity.type).c_str(),
android::internal::ToString(id).c_str());
return runWithActiveSubEffectThenOthers(
[&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 0dcb8ee..f278ca0 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -28,6 +28,7 @@
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionEffect.h>
#include <system/audio.h>
+#include <system/audio_aidl_utils.h>
#include <utils/Log.h>
#include "EffectBufferHalAidl.h"
@@ -40,7 +41,10 @@
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::IFactory;
using ::aidl::android::hardware::audio::effect::Processing;
+using ::aidl::android::media::audio::common::AudioSource;
+using ::aidl::android::media::audio::common::AudioStreamType;
using ::aidl::android::media::audio::common::AudioUuid;
+using ::android::audio::utils::toString;
using ::android::base::unexpected;
using ::android::detail::AudioHalVersionInfo;
@@ -96,7 +100,13 @@
return list;
}()),
mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
- mEffectProcessings(nullptr /* TODO: add AIDL implementation */) {
+ mAidlProcessings([this]() -> std::vector<Processing> {
+ std::vector<Processing> processings;
+ if (!mFactory || !mFactory->queryProcessing(std::nullopt, &processings).isOk()) {
+ ALOGE("%s queryProcessing failed", __func__);
+ }
+ return processings;
+ }()) {
ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
mProxyDescList.size());
@@ -180,7 +190,7 @@
statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
}
if (aidlEffect == nullptr) {
- ALOGE("%s failed to create effect with UUID: %s", __func__, aidlUuid.toString().c_str());
+ ALOGE("%s failed to create effect with UUID: %s", __func__, toString(aidlUuid).c_str());
return NAME_NOT_FOUND;
}
Descriptor desc;
@@ -236,10 +246,10 @@
auto matchIt = std::find_if(list.begin(), list.end(),
[&](const auto& desc) { return desc.common.id.uuid == uuid; });
if (matchIt == list.end()) {
- ALOGE("%s UUID not found in HAL and proxy list %s", __func__, uuid.toString().c_str());
+ ALOGE("%s UUID not found in HAL and proxy list %s", __func__, toString(uuid).c_str());
return BAD_VALUE;
}
- ALOGI("%s UUID impl found %s", __func__, uuid.toString().c_str());
+ ALOGI("%s UUID impl found %s", __func__, toString(uuid).c_str());
*pDescriptor = VALUE_OR_RETURN_STATUS(
::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
@@ -258,10 +268,10 @@
std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
[&](auto& desc) { return desc.common.id.type == type; });
if (result.empty()) {
- ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, type.toString().c_str());
+ ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, toString(type).c_str());
return BAD_VALUE;
}
- ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), type.toString().c_str());
+ ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), toString(type).c_str());
*descriptors = VALUE_OR_RETURN_STATUS(
aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
@@ -274,15 +284,79 @@
}
std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
- return mEffectProcessings;
+
+ auto getConfigEffectWithDescriptor =
+ [](const auto& desc) -> std::shared_ptr<const effectsConfig::Effect> {
+ effectsConfig::Effect effect = {.name = desc.common.name, .isProxy = false};
+ if (const auto uuid =
+ ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(desc.common.id.uuid);
+ uuid.ok()) {
+ static_cast<effectsConfig::EffectImpl>(effect).uuid = uuid.value();
+ return std::make_shared<const effectsConfig::Effect>(effect);
+ } else {
+ return nullptr;
+ }
+ };
+
+ auto getConfigProcessingWithAidlProcessing =
+ [&](const auto& aidlProcess, std::vector<effectsConfig::InputStream>& preprocess,
+ std::vector<effectsConfig::OutputStream>& postprocess) {
+ if (aidlProcess.type.getTag() == Processing::Type::streamType) {
+ AudioStreamType aidlType =
+ aidlProcess.type.template get<Processing::Type::streamType>();
+ const auto type =
+ ::aidl::android::aidl2legacy_AudioStreamType_audio_stream_type_t(
+ aidlType);
+ if (!type.ok()) {
+ return;
+ }
+
+ std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+ std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+ std::back_inserter(effects), getConfigEffectWithDescriptor);
+ effectsConfig::OutputStream stream = {.type = type.value(),
+ .effects = std::move(effects)};
+ postprocess.emplace_back(stream);
+ } else if (aidlProcess.type.getTag() == Processing::Type::source) {
+ AudioSource aidlType =
+ aidlProcess.type.template get<Processing::Type::source>();
+ const auto type =
+ ::aidl::android::aidl2legacy_AudioSource_audio_source_t(aidlType);
+ if (!type.ok()) {
+ return;
+ }
+
+ std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+ std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+ std::back_inserter(effects), getConfigEffectWithDescriptor);
+ effectsConfig::InputStream stream = {.type = type.value(),
+ .effects = std::move(effects)};
+ preprocess.emplace_back(stream);
+ }
+ };
+
+ static std::shared_ptr<const effectsConfig::Processings> processings(
+ [&]() -> std::shared_ptr<const effectsConfig::Processings> {
+ std::vector<effectsConfig::InputStream> preprocess;
+ std::vector<effectsConfig::OutputStream> postprocess;
+ for (const auto& processing : mAidlProcessings) {
+ getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess);
+ }
+
+ if (0 == preprocess.size() && 0 == postprocess.size()) {
+ return nullptr;
+ }
+
+ return std::make_shared<const effectsConfig::Processings>(
+ effectsConfig::Processings({.preprocess = std::move(preprocess),
+ .postprocess = std::move(postprocess)}));
+ }());
+
+ return processings;
}
+// Return 0 for AIDL, as the AIDL interface is not aware of the configuration file.
::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
- if (!mEffectProcessings) {
- return ::android::base::unexpected(BAD_VALUE);
- }
-
- // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file
return 0;
}
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 70a7012..39beea2 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -21,6 +21,7 @@
#include <mutex>
#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/hardware/audio/effect/Processing.h>
#include <android-base/thread_annotations.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <system/thread_defs.h>
@@ -82,7 +83,7 @@
// total number of effects including proxy effects
const size_t mEffectCount;
// Query result of pre and post processing from effect factory
- const std::shared_ptr<const effectsConfig::Processings> mEffectProcessings;
+ const std::vector<Processing> mAidlProcessings;
std::mutex mLock;
uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index eccdfe8..d1044dc 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -122,30 +122,6 @@
return OK;
}
-namespace {
-
-// 'action' must accept a value of type 'T' and return 'status_t'.
-// The function returns 'true' if the parameter was found, and the action has succeeded.
-// The function returns 'false' if the parameter was not found.
-// Any errors get propagated, if there are errors it means the parameter was found.
-template<typename T, typename F>
-error::Result<bool> filterOutAndProcessParameter(
- AudioParameter& parameters, const String8& key, const F& action) {
- if (parameters.containsKey(key)) {
- T value;
- status_t status = parameters.get(key, value);
- if (status == OK) {
- parameters.remove(key);
- status = action(value);
- if (status == OK) return true;
- }
- return base::unexpected(status);
- }
- return false;
-}
-
-} // namespace
-
status_t StreamHalAidl::setParameters(const String8& kvPairs) {
TIME_CHECK();
if (!mStream) return NO_INIT;
@@ -579,10 +555,10 @@
if (!mStream) return NO_INIT;
AudioParameter parameters(kvPairs);
- ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
+ ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
- ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
+ ALOGW("%s: filtering or updating offload metadata failed: %d", __func__, status);
}
return StreamHalAidl::setParameters(parameters.toString());
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index b0f8656..0103680 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -19,6 +19,7 @@
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioMode.h>
#include <android/media/audio/common/AudioPort.h>
#include <android/media/AudioRoute.h>
#include <error/Result.h>
@@ -40,6 +41,8 @@
virtual status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) = 0;
+ virtual status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) = 0;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
virtual status_t getSupportedDevices(uint32_t *devices) = 0;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 8210f7d..8f011c8 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -21,34 +21,34 @@
}
cc_defaults {
- name: "AudioHalTestDefaults",
+ name: "libaudiohal_aidl_test_default",
test_suites: ["device-tests"],
defaults: [
- "latest_android_media_audio_common_types_ndk_shared",
+ "libaudiohal_default",
+ "libaudiohal_aidl_default",
],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wthread-safety",
- "-DBACKEND_NDK",
- ],
-
shared_libs: [
- "audioclient-types-aidl-cpp",
- "libaudio_aidl_conversion_common_ndk",
"libaudiohal",
- "liblog",
- "libutils",
- "libvibrator",
],
}
cc_test {
+ name: "CoreAudioHalAidlTest",
+ srcs: [
+ "CoreAudioHalAidl_test.cpp",
+ ":core_audio_hal_aidl_src_files",
+ ],
+ defaults: ["libaudiohal_aidl_test_default"],
+ header_libs: ["libaudiohalimpl_headers"],
+}
+
+cc_test {
name: "EffectsFactoryHalInterfaceTest",
srcs: ["EffectsFactoryHalInterface_test.cpp"],
- defaults: ["AudioHalTestDefaults"],
- header_libs: ["libaudiohal_headers"],
+ defaults: ["libaudiohal_aidl_test_default"],
+ shared_libs: [
+ "libvibrator",
+ ],
}
cc_test {
@@ -58,15 +58,8 @@
":audio_effectproxy_src_files",
],
defaults: [
- "AudioHalTestDefaults",
- "latest_android_hardware_audio_effect_ndk_shared",
- "libaudiohal_default",
+ "libaudiohal_aidl_test_default",
"use_libaidlvintf_gtest_helper_static",
],
- shared_libs: [
- "android.hardware.common.fmq-V1-ndk",
- "libbinder_ndk",
- "libfmq",
- ],
header_libs: ["libaudiohalimpl_headers"],
}
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
new file mode 100644
index 0000000..8433c48
--- /dev/null
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2023 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 <memory>
+
+#define LOG_TAG "CoreAudioHalAidlTest"
+#include <gtest/gtest.h>
+
+#include <DeviceHalAidl.h>
+#include <aidl/android/hardware/audio/core/BnModule.h>
+#include <utils/Log.h>
+
+namespace {
+
+class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule {
+ public:
+ bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
+ ScreenRotation getScreenRotation() const { return mScreenRotation; }
+
+ private:
+ ndk::ScopedAStatus setModuleDebug(
+ const ::aidl::android::hardware::audio::core::ModuleDebug&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getTelephony(
+ std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getBluetooth(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getBluetoothA2dp(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getBluetoothLe(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus connectExternalDevice(
+ const ::aidl::android::media::audio::common::AudioPort&,
+ ::aidl::android::media::audio::common::AudioPort*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus disconnectExternalDevice(int32_t) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPatches(
+ std::vector<::aidl::android::hardware::audio::core::AudioPatch>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPort(int32_t,
+ ::aidl::android::media::audio::common::AudioPort*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPortConfigs(
+ std::vector<::aidl::android::media::audio::common::AudioPortConfig>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPorts(
+ std::vector<::aidl::android::media::audio::common::AudioPort>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioRoutes(
+ std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioRoutesForAudioPort(
+ int32_t, std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus openInputStream(const OpenInputStreamArguments&,
+ OpenInputStreamReturn*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
+ OpenOutputStreamReturn*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setAudioPatch(const ::aidl::android::hardware::audio::core::AudioPatch&,
+ ::aidl::android::hardware::audio::core::AudioPatch*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setAudioPortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig&,
+ ::aidl::android::media::audio::common::AudioPortConfig*, bool*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus resetAudioPatch(int32_t) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus resetAudioPortConfig(int32_t) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMasterMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus setMasterMute(bool) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMasterVolume(float*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus setMasterVolume(float) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMicMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus setMicMute(bool) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMicrophones(
+ std::vector<::aidl::android::media::audio::common::MicrophoneInfo>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus updateAudioMode(::aidl::android::media::audio::common::AudioMode) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus updateScreenRotation(ScreenRotation in_rotation) override {
+ mScreenRotation = in_rotation;
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override {
+ mIsScreenTurnedOn = in_isTurnedOn;
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getSoundDose(
+ std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>*)
+ override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getVendorParameters(
+ const std::vector<std::string>&,
+ std::vector<::aidl::android::hardware::audio::core::VendorParameter>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setVendorParameters(
+ const std::vector<::aidl::android::hardware::audio::core::VendorParameter>&,
+ bool) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus addDeviceEffect(
+ int32_t,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus removeDeviceEffect(
+ int32_t,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getMmapPolicyInfos(
+ ::aidl::android::media::audio::common::AudioMMapPolicyType,
+ std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus supportsVariableLatency(bool*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+
+ bool mIsScreenTurnedOn = false;
+ ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
+};
+
+android::String8 createParameterString(const char* key, const char* value) {
+ android::AudioParameter params;
+ params.add(android::String8(key), android::String8(value));
+ return params.toString();
+}
+
+android::String8 createParameterString(const char* key, int value) {
+ android::AudioParameter params;
+ params.addInt(android::String8(key), value);
+ return params.toString();
+}
+
+template <typename>
+struct mf_traits {};
+template <class T, class U>
+struct mf_traits<U T::*> {
+ using member_type = U;
+};
+
+} // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace aidl::android::hardware::audio::core {
+template <typename P>
+std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+ std::ostream&>
+operator<<(std::ostream& os, const P& p) {
+ return os << p.toString();
+}
+template <typename E>
+std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+ return os << toString(e);
+}
+} // namespace aidl::android::hardware::audio::core
+
+using namespace android;
+
+class DeviceHalAidlTest : public testing::Test {
+ public:
+ void SetUp() override {
+ mModule = ndk::SharedRefBase::make<ModuleMock>();
+ mDevice = sp<DeviceHalAidl>::make("test", mModule);
+ }
+ void TearDown() override {
+ mDevice.clear();
+ mModule.reset();
+ }
+
+ protected:
+ std::shared_ptr<ModuleMock> mModule;
+ sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlTest, ScreenState) {
+ EXPECT_FALSE(mModule->isScreenTurnedOn());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+ AudioParameter::valueOn)));
+ EXPECT_TRUE(mModule->isScreenTurnedOn());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+ AudioParameter::valueOff)));
+ EXPECT_FALSE(mModule->isScreenTurnedOn());
+ // The adaptation layer only logs a warning.
+ EXPECT_EQ(OK, mDevice->setParameters(
+ createParameterString(AudioParameter::keyScreenState, "blah")));
+ EXPECT_FALSE(mModule->isScreenTurnedOn());
+}
+
+TEST_F(DeviceHalAidlTest, ScreenRotation) {
+ using ScreenRotation = ::aidl::android::hardware::audio::core::IModule::ScreenRotation;
+ EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+ EXPECT_EQ(OK,
+ mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 90)));
+ EXPECT_EQ(ScreenRotation::DEG_90, mModule->getScreenRotation());
+ EXPECT_EQ(OK,
+ mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 0)));
+ EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+ // The adaptation layer only logs a warning.
+ EXPECT_EQ(OK,
+ mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
+ EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+}
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index c076ccc..63f895f 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -15,6 +15,7 @@
*/
//#define LOG_NDEBUG 0
+#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
@@ -92,6 +93,47 @@
}
}
+TEST(libAudioHalTest, getProcessings) {
+ auto factory = EffectsFactoryHalInterface::create();
+ ASSERT_NE(nullptr, factory);
+
+ const auto &processings = factory->getProcessings();
+ if (processings) {
+ EXPECT_NE(0UL, processings->preprocess.size() + processings->postprocess.size() +
+ processings->deviceprocess.size());
+
+ auto processingChecker = [](const auto& processings) {
+ if (processings.size() != 0) {
+ // any process need at least 1 effect inside
+ std::for_each(processings.begin(), processings.end(), [](const auto& process) {
+ EXPECT_NE(0ul, process.effects.size());
+ // any effect should have a valid name string, and not proxy
+ for (const auto& effect : process.effects) {
+ SCOPED_TRACE("Effect: {" +
+ (effect == nullptr
+ ? "NULL}"
+ : ("{name: " + effect->name + ", isproxy: " +
+ (effect->isProxy ? "true" : "false") + ", sw: " +
+ (effect->libSw ? "non-null" : "null") + ", hw: " +
+ (effect->libHw ? "non-null" : "null") + "}")));
+ EXPECT_NE(nullptr, effect);
+ EXPECT_NE("", effect->name);
+ EXPECT_EQ(false, effect->isProxy);
+ EXPECT_EQ(nullptr, effect->libSw);
+ EXPECT_EQ(nullptr, effect->libHw);
+ }
+ });
+ }
+ };
+
+ processingChecker(processings->preprocess);
+ processingChecker(processings->postprocess);
+ processingChecker(processings->deviceprocess);
+ } else {
+ GTEST_SKIP() << "no processing found, skipping the test";
+ }
+}
+
TEST(libAudioHalTest, getHalVersion) {
auto factory = EffectsFactoryHalInterface::create();
ASSERT_NE(nullptr, factory);
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index a9730e5..09a060d 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -49,26 +49,27 @@
std::string name;
std::string path;
};
-using Libraries = std::vector<Library>;
+using Libraries = std::vector<std::shared_ptr<const Library>>;
struct EffectImpl {
- Library* library; //< Only valid as long as the associated library vector is unmodified
+ //< Only valid as long as the associated library vector is unmodified
+ std::shared_ptr<const Library> library;
effect_uuid_t uuid;
};
struct Effect : public EffectImpl {
std::string name;
bool isProxy;
- EffectImpl libSw; //< Only valid if isProxy
- EffectImpl libHw; //< Only valid if isProxy
+ std::shared_ptr<EffectImpl> libSw; //< Only valid if isProxy
+ std::shared_ptr<EffectImpl> libHw; //< Only valid if isProxy
};
-using Effects = std::vector<Effect>;
+using Effects = std::vector<std::shared_ptr<const Effect>>;
template <class Type>
struct Stream {
Type type;
- std::vector<std::reference_wrapper<Effect>> effects;
+ Effects effects;
};
using OutputStream = Stream<audio_stream_type_t>;
using InputStream = Stream<audio_source_t>;
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 3096659..2ff057e 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -19,6 +19,7 @@
#include <algorithm>
#include <cstdint>
#include <functional>
+#include <memory>
#include <string>
#include <unistd.h>
@@ -149,7 +150,10 @@
ALOGE("library must have a name and a path: %s", dump(xmlLibrary));
return false;
}
- libraries->push_back({name, path});
+
+ // need this temp variable because `struct Library` doesn't have a constructor
+ Library lib({.name = name, .path = path});
+ libraries->push_back(std::make_shared<const Library>(lib));
return true;
}
@@ -157,10 +161,10 @@
* @return nullptr if not found, the element address if found.
*/
template <class T>
-T* findByName(const char* name, std::vector<T>& collection) {
+T findByName(const char* name, std::vector<T>& collection) {
auto it = find_if(begin(collection), end(collection),
- [name] (auto& item) { return item.name == name; });
- return it != end(collection) ? &*it : nullptr;
+ [name](auto& item) { return item && item->name == name; });
+ return it != end(collection) ? *it : nullptr;
}
/** Parse an effect from an xml element describing it.
@@ -187,7 +191,7 @@
}
// Convert library name to a pointer to the previously loaded library
- auto* library = findByName(libraryName, libraries);
+ auto library = findByName(libraryName, libraries);
if (library == nullptr) {
ALOGE("Could not find library referenced in: %s", dump(xmlImpl));
return false;
@@ -211,20 +215,25 @@
effect.isProxy = true;
// Function to parse libhw and libsw
- auto parseProxy = [&xmlEffect, &parseImpl](const char* tag, EffectImpl& proxyLib) {
+ auto parseProxy = [&xmlEffect, &parseImpl](const char* tag,
+ const std::shared_ptr<EffectImpl>& proxyLib) {
auto* xmlProxyLib = xmlEffect.FirstChildElement(tag);
if (xmlProxyLib == nullptr) {
ALOGE("effectProxy must contain a <%s>: %s", tag, dump(xmlEffect));
return false;
}
- return parseImpl(*xmlProxyLib, proxyLib);
+ return parseImpl(*xmlProxyLib, *proxyLib);
};
+ effect.libSw = std::make_shared<EffectImpl>();
+ effect.libHw = std::make_shared<EffectImpl>();
if (!parseProxy("libhw", effect.libHw) || !parseProxy("libsw", effect.libSw)) {
+ effect.libSw.reset();
+ effect.libHw.reset();
return false;
}
}
- effects->push_back(std::move(effect));
+ effects->push_back(std::make_shared<const Effect>(effect));
return true;
}
@@ -250,12 +259,12 @@
ALOGE("<stream|device>/apply must have reference an effect: %s", dump(xmlApply));
return false;
}
- auto* effect = findByName(effectName, effects);
+ auto effect = findByName(effectName, effects);
if (effect == nullptr) {
ALOGE("Could not find effect referenced in: %s", dump(xmlApply));
return false;
}
- stream.effects.emplace_back(*effect);
+ stream.effects.emplace_back(effect);
}
streams->push_back(std::move(stream));
return true;
diff --git a/media/libeffects/factory/EffectsConfigLoader.c b/media/libeffects/factory/EffectsConfigLoader.c
index e23530e..a1de7b3 100644
--- a/media/libeffects/factory/EffectsConfigLoader.c
+++ b/media/libeffects/factory/EffectsConfigLoader.c
@@ -137,7 +137,7 @@
kLibraryPathRoot[i],
lib_name);
if (F_OK == access(path, 0)) {
- strcpy(lib_path_out, path);
+ strlcpy(lib_path_out, path, PATH_MAX);
ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
"checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
return 0;
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
index 30a9007..9bff136 100644
--- a/media/libeffects/factory/EffectsXmlConfigLoader.cpp
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -64,7 +64,7 @@
std::string absolutePath;
if (!resolveLibrary(relativePath, &absolutePath)) {
- ALOGE("Could not find library in effect directories: %s", relativePath);
+ ALOGE("%s Could not find library in effect directories: %s", __func__, relativePath);
libEntry->path = strdup(relativePath);
return false;
}
@@ -75,20 +75,20 @@
std::unique_ptr<void, decltype(dlclose)*> libHandle(dlopen(path, RTLD_NOW),
dlclose);
if (libHandle == nullptr) {
- ALOGE("Could not dlopen library %s: %s", path, dlerror());
+ ALOGE("%s Could not dlopen library %s: %s", __func__, path, dlerror());
return false;
}
auto* description = static_cast<audio_effect_library_t*>(
dlsym(libHandle.get(), AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR));
if (description == nullptr) {
- ALOGE("Invalid effect library, failed not find symbol '%s' in %s: %s",
+ ALOGE("%s Invalid effect library, failed not find symbol '%s' in %s: %s", __func__,
AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR, path, dlerror());
return false;
}
if (description->tag != AUDIO_EFFECT_LIBRARY_TAG) {
- ALOGE("Bad tag %#08x in description structure, expected %#08x for library %s",
+ ALOGE("%s Bad tag %#08x in description structure, expected %#08x for library %s", __func__,
description->tag, AUDIO_EFFECT_LIBRARY_TAG, path);
return false;
}
@@ -96,8 +96,8 @@
uint32_t majorVersion = EFFECT_API_VERSION_MAJOR(description->version);
uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION_CURRENT);
if (majorVersion != expectedMajorVersion) {
- ALOGE("Unsupported major version %#08x, expected %#08x for library %s",
- majorVersion, expectedMajorVersion, path);
+ ALOGE("%s Unsupported major version %#08x, expected %#08x for library %s",
+ __func__, majorVersion, expectedMajorVersion, path);
return false;
}
@@ -155,14 +155,13 @@
{
size_t nbSkippedElement = 0;
for (auto& library : libs) {
-
// Construct a lib entry
auto libEntry = makeUniqueC<lib_entry_t>();
- libEntry->name = strdup(library.name.c_str());
+ libEntry->name = strdup(library->name.c_str());
libEntry->effects = nullptr;
pthread_mutex_init(&libEntry->lock, nullptr);
- if (!loadLibrary(library.path.c_str(), libEntry.get())) {
+ if (!loadLibrary(library->path.c_str(), libEntry.get())) {
// Register library load failure
listPush(std::move(libEntry), libFailedList);
++nbSkippedElement;
@@ -209,24 +208,24 @@
UniqueCPtr<effect_descriptor_t> effectDesc;
};
-LoadEffectResult loadEffect(const EffectImpl& effect, const std::string& name,
- list_elem_t* libList) {
+LoadEffectResult loadEffect(const std::shared_ptr<const EffectImpl>& effect,
+ const std::string& name, list_elem_t* libList) {
LoadEffectResult result;
// Find the effect library
- result.lib = findLibrary(effect.library->name.c_str(), libList);
+ result.lib = findLibrary(effect->library->name.c_str(), libList);
if (result.lib == nullptr) {
- ALOGE("Could not find library %s to load effect %s",
- effect.library->name.c_str(), name.c_str());
+ ALOGE("%s Could not find library %s to load effect %s",
+ __func__, effect->library->name.c_str(), name.c_str());
return result;
}
result.effectDesc = makeUniqueC<effect_descriptor_t>();
// Get the effect descriptor
- if (result.lib->desc->get_descriptor(&effect.uuid, result.effectDesc.get()) != 0) {
+ if (result.lib->desc->get_descriptor(&effect->uuid, result.effectDesc.get()) != 0) {
ALOGE("Error querying effect %s on lib %s",
- uuidToString(effect.uuid), result.lib->name);
+ uuidToString(effect->uuid), result.lib->name);
result.effectDesc.reset();
return result;
}
@@ -241,14 +240,15 @@
// Check effect is supported
uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION);
if (EFFECT_API_VERSION_MAJOR(result.effectDesc->apiVersion) != expectedMajorVersion) {
- ALOGE("Bad API version %#08x for effect %s in lib %s, expected major %#08x",
+ ALOGE("%s Bad API version %#08x for effect %s in lib %s, expected major %#08x", __func__,
result.effectDesc->apiVersion, name.c_str(), result.lib->name, expectedMajorVersion);
return result;
}
lib_entry_t *_;
- if (findEffect(nullptr, &effect.uuid, &_, nullptr) == 0) {
- ALOGE("Effect %s uuid %s already exist", uuidToString(effect.uuid), name.c_str());
+ if (findEffect(nullptr, &effect->uuid, &_, nullptr) == 0) {
+ ALOGE("%s Effect %s uuid %s already exist", __func__, uuidToString(effect->uuid),
+ name.c_str());
return result;
}
@@ -261,8 +261,11 @@
size_t nbSkippedElement = 0;
for (auto& effect : effects) {
+ if (!effect) {
+ continue;
+ }
- auto effectLoadResult = loadEffect(effect, effect.name, libList);
+ auto effectLoadResult = loadEffect(effect, effect->name, libList);
if (!effectLoadResult.success) {
if (effectLoadResult.effectDesc != nullptr) {
listPush(std::move(effectLoadResult.effectDesc), skippedEffects);
@@ -271,9 +274,9 @@
continue;
}
- if (effect.isProxy) {
- auto swEffectLoadResult = loadEffect(effect.libSw, effect.name + " libsw", libList);
- auto hwEffectLoadResult = loadEffect(effect.libHw, effect.name + " libhw", libList);
+ if (effect->isProxy) {
+ auto swEffectLoadResult = loadEffect(effect->libSw, effect->name + " libsw", libList);
+ auto hwEffectLoadResult = loadEffect(effect->libHw, effect->name + " libhw", libList);
if (!swEffectLoadResult.success || !hwEffectLoadResult.success) {
// Push the main effect in the skipped list even if only a subeffect is invalid
// as the main effect is not usable without its subeffects.
@@ -287,7 +290,7 @@
// get_descriptor call, we replace it with the corresponding
// sw effect descriptor, but keep the Proxy UUID
*effectLoadResult.effectDesc = *swEffectLoadResult.effectDesc;
- effectLoadResult.effectDesc->uuid = effect.uuid;
+ effectLoadResult.effectDesc->uuid = effect->uuid;
effectLoadResult.effectDesc->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
@@ -326,8 +329,8 @@
loadEffects(result.parsedConfig->effects, gLibraryList,
&gSkippedEffects, &gSubEffectList);
- ALOGE_IF(result.nbSkippedElement != 0, "%zu errors during loading of configuration: %s",
- result.nbSkippedElement,
+ ALOGE_IF(result.nbSkippedElement != 0, "%s %zu errors during loading of configuration: %s",
+ __func__, result.nbSkippedElement,
result.configPath.empty() ? "No config file found" : result.configPath.c_str());
return result.nbSkippedElement;
diff --git a/media/libeffects/factory/test/DumpConfig.cpp b/media/libeffects/factory/test/DumpConfig.cpp
index 0a156b4..331826f 100644
--- a/media/libeffects/factory/test/DumpConfig.cpp
+++ b/media/libeffects/factory/test/DumpConfig.cpp
@@ -14,54 +14,49 @@
* limitations under the License.
*/
+#include <getopt.h>
+
#include <media/EffectsFactoryApi.h>
-#include <unistd.h>
#include "EffectsXmlConfigLoader.h"
#include "EffectsConfigLoader.h"
int main(int argc, char* argv[]) {
- const char* path = nullptr;
- bool legacyFormat;
+ const char* const short_opts = "lx:h";
+ const option long_opts[] = {{"legacy", no_argument, nullptr, 'l'},
+ {"xml", optional_argument, nullptr, 'x'},
+ {"help", no_argument, nullptr, 'h'}};
- if (argc == 2 && strcmp(argv[1], "--legacy") == 0) {
- legacyFormat = true;
- fprintf(stderr, "Dumping legacy effect config file\n");
- } else if ((argc == 2 || argc == 3) && strcmp(argv[1], "--xml") == 0) {
- legacyFormat = false;
- if (argc == 3) {
- fprintf(stderr, "Dumping XML effect config file: %s\n", path);
- } else {
- fprintf(stderr, "Dumping default XML effect config file.\n");
+ const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);
+ switch (opt) {
+ case 'l': { // -l or --legacy
+ printf("Dumping legacy effect config file\n");
+ if (EffectLoadEffectConfig() < 0) {
+ fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
+ return 1;
+ }
+ return EffectDumpEffects(STDOUT_FILENO);
}
- } else {
- fprintf(stderr, "Invalid arguments.\n"
- "Usage: %s [--legacy|--xml [FILE]]\n", argv[0]);
- return 1;
- }
-
- if (!legacyFormat) {
- ssize_t ret = EffectLoadXmlEffectConfig(path);
- if (ret < 0) {
- fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
- return 2;
+ case 'x': { // -x or --xml
+ printf("Dumping effect config file: %s\n", (optarg == NULL) ? "default" : optarg);
+ ssize_t ret = EffectLoadXmlEffectConfig(optarg);
+ if (ret < 0) {
+ fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
+ return 1;
+ }
+ if (ret > 0) {
+ printf("Partially failed to load config. Skipped %zu elements.\n",
+ (size_t)ret);
+ }
+ return EffectDumpEffects(STDOUT_FILENO);
}
- if (ret > 0) {
- fprintf(stderr, "Partially failed to load config. Skipped %zu elements, "
- "see logcat for detail.\n", (size_t)ret);
+ case 'h': // -h or --help
+ default: {
+ printf("Usage: %s\n"
+ "--legacy (or -l): Legacy audio effect config file to load\n"
+ "--xml (or -x) <FILE>: Audio effect config file to load\n"
+ "--help (or -h): Show this help\n",
+ argv[0]);
+ return 0;
}
}
-
- if (legacyFormat) {
- auto ret = EffectLoadEffectConfig();
- if (ret < 0) {
- fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
- return 3;
- }
- fprintf(stderr, "legacy loadEffectConfig has probably succeed, see logcat to make sure.\n");
- }
-
- if (EffectDumpEffects(STDOUT_FILENO) != 0) {
- fprintf(stderr, "Effect dump failed, see logcat for detail.\n");
- return 4;
- }
}
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index b3371a3..3bc889c 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -85,9 +85,7 @@
static const std::string kEqualizerEffectName = "EqualizerBundle";
static const Descriptor kEqualizerDesc = {
.common = {.id = {.type = getEffectTypeUuidEqualizer(),
- .uuid = getEffectImplUuidEqualizerBundle(),
- .proxy = getEffectImplUuidEqualizerProxy()},
-
+ .uuid = getEffectImplUuidEqualizerBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
@@ -102,8 +100,7 @@
static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
static const Descriptor kBassBoostDesc = {
.common = {.id = {.type = getEffectTypeUuidBassBoost(),
- .uuid = getEffectImplUuidBassBoostBundle(),
- .proxy = getEffectImplUuidBassBoostProxy()},
+ .uuid = getEffectImplUuidBassBoostBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL,
@@ -121,8 +118,7 @@
static const Descriptor kVirtualizerDesc = {
.common = {.id = {.type = getEffectTypeUuidVirtualizer(),
- .uuid = getEffectImplUuidVirtualizerBundle(),
- .proxy = getEffectImplUuidVirtualizerProxy()},
+ .uuid = getEffectImplUuidVirtualizerBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::LAST,
.volume = Flags::Volume::CTRL,
@@ -139,8 +135,7 @@
static const std::string kVolumeEffectName = "Volume";
static const Descriptor kVolumeDesc = {
.common = {.id = {.type = getEffectTypeUuidVolume(),
- .uuid = getEffectImplUuidVolumeBundle(),
- .proxy = std::nullopt},
+ .uuid = getEffectImplUuidVolumeBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::LAST,
.volume = Flags::Volume::CTRL},
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index c66861b..649f813 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -49,8 +49,9 @@
"liblog",
],
header_libs: [
- "libmedia_helper_headers",
"libaudio_system_headers",
+ "libhardware_headers",
+ "libmedia_helper_headers",
],
export_header_lib_headers: [
"libmedia_helper_headers",
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index e25f9b7..3832e90 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -20,6 +20,7 @@
#include <utils/Log.h>
#include <media/AudioParameter.h>
+#include <hardware/audio.h>
#include <system/audio.h>
namespace android {
@@ -32,9 +33,16 @@
const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+const char * const AudioParameter::keyScreenRotation = AUDIO_PARAMETER_KEY_ROTATION;
const char * const AudioParameter::keyClosing = AUDIO_PARAMETER_KEY_CLOSING;
const char * const AudioParameter::keyExiting = AUDIO_PARAMETER_KEY_EXITING;
+const char * const AudioParameter::keyBtSco = AUDIO_PARAMETER_KEY_BT_SCO;
+const char * const AudioParameter::keyBtScoHeadsetName = AUDIO_PARAMETER_KEY_BT_SCO_HEADSET_NAME;
const char * const AudioParameter::keyBtNrec = AUDIO_PARAMETER_KEY_BT_NREC;
+const char * const AudioParameter::keyBtScoWb = AUDIO_PARAMETER_KEY_BT_SCO_WB;
+const char * const AudioParameter::keyBtHfpEnable = AUDIO_PARAMETER_KEY_HFP_ENABLE;
+const char * const AudioParameter::keyBtHfpSamplingRate = AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE;
+const char * const AudioParameter::keyBtHfpVolume = AUDIO_PARAMETER_KEY_HFP_VOLUME;
const char * const AudioParameter::keyHwAvSync = AUDIO_PARAMETER_HW_AV_SYNC;
const char * const AudioParameter::keyPresentationId = AUDIO_PARAMETER_STREAM_PRESENTATION_ID;
const char * const AudioParameter::keyProgramId = AUDIO_PARAMETER_STREAM_PROGRAM_ID;
@@ -52,9 +60,13 @@
AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES;
const char * const AudioParameter::valueOn = AUDIO_PARAMETER_VALUE_ON;
const char * const AudioParameter::valueOff = AUDIO_PARAMETER_VALUE_OFF;
+const char * const AudioParameter::valueTrue = AUDIO_PARAMETER_VALUE_TRUE;
+const char * const AudioParameter::valueFalse = AUDIO_PARAMETER_VALUE_FALSE;
const char * const AudioParameter::valueListSeparator = AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
+const char * const AudioParameter::keyBtA2dpSuspended = AUDIO_PARAMETER_KEY_BT_A2DP_SUSPENDED;
const char * const AudioParameter::keyReconfigA2dp = AUDIO_PARAMETER_RECONFIG_A2DP;
const char * const AudioParameter::keyReconfigA2dpSupported = AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED;
+const char * const AudioParameter::keyBtLeSuspended = AUDIO_PARAMETER_KEY_BT_LE_SUSPENDED;
// const char * const AudioParameter::keyDeviceSupportedEncapsulationModes =
// AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES;
// const char * const AudioParameter::keyDeviceSupportedEncapsulationMetadataTypes =
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 6c34a4f..8568b8f 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -41,6 +41,7 @@
// keyInputSource: to change audio input source, value is an int in audio_source_t
// (defined in media/mediarecorder.h)
// keyScreenState: either "on" or "off"
+ // keyScreenRotation: one of: 0, 90, 180, 270
static const char * const keyRouting;
static const char * const keySamplingRate;
static const char * const keyFormat;
@@ -48,6 +49,7 @@
static const char * const keyFrameCount;
static const char * const keyInputSource;
static const char * const keyScreenState;
+ static const char * const keyScreenRotation;
// TODO(b/73175392) consider improvement to AIDL StreamOut interface.
// keyClosing: "true" when AudioOutputDescriptor is closing. Used by A2DP HAL.
@@ -55,11 +57,22 @@
static const char * const keyClosing;
static const char * const keyExiting;
+ // keyBtSco: Whether BT SCO is 'on' or 'off'
+ // keyBtScoHeadsetName: BT SCO headset name (for debugging)
// keyBtNrec: BT SCO Noise Reduction + Echo Cancellation parameters
+ // keyBtScoWb: BT SCO NR wideband mode
+ // keyHfp...: Parameters of the Hands-Free Profile
+ static const char * const keyBtSco;
+ static const char * const keyBtScoHeadsetName;
+ static const char * const keyBtNrec;
+ static const char * const keyBtScoWb;
+ static const char * const keyBtHfpEnable;
+ static const char * const keyBtHfpSamplingRate;
+ static const char * const keyBtHfpVolume;
+
// keyHwAvSync: get HW synchronization source identifier from a device
// keyMonoOutput: Enable mono audio playback
// keyStreamHwAvSync: set HW synchronization source identifier on a stream
- static const char * const keyBtNrec;
static const char * const keyHwAvSync;
static const char * const keyMonoOutput;
static const char * const keyStreamHwAvSync;
@@ -90,13 +103,19 @@
static const char * const valueOn;
static const char * const valueOff;
+ static const char * const valueTrue;
+ static const char * const valueFalse;
static const char * const valueListSeparator;
+ // keyBtA2dpSuspended: 'true' or 'false'
// keyReconfigA2dp: Ask HwModule to reconfigure A2DP offloaded codec
// keyReconfigA2dpSupported: Query if HwModule supports A2DP offload codec config
+ // keyBtLeSuspended: 'true' or 'false'
+ static const char * const keyBtA2dpSuspended;
static const char * const keyReconfigA2dp;
static const char * const keyReconfigA2dpSupported;
+ static const char * const keyBtLeSuspended;
// For querying device supported encapsulation capabilities. All returned values are integer,
// which are bit fields composed from using encapsulation capability values as position bits.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d205990..f73c5a8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2217,6 +2217,11 @@
-ret, strerror(-ret));
return ret;
}
+ if (mVideoDecoder != NULL) {
+ sp<AMessage> params = new AMessage();
+ params->setInt32("android._video-scaling", mode);
+ mVideoDecoder->setParameters(params);
+ }
}
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 8da09c4..f4143da 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -459,6 +459,14 @@
codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
mCodec->setParameters(codecParams);
}
+
+ int32_t videoScalingMode;
+ if (params->findInt32("android._video-scaling", &videoScalingMode)
+ && mCodec != NULL) {
+ sp<AMessage> codecParams = new AMessage();
+ codecParams->setInt32("android._video-scaling", videoScalingMode);
+ mCodec->setParameters(codecParams);
+ }
}
void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ccbe995..47cc357 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -293,6 +293,8 @@
}
}
+ void setSurfaceParameters(const sp<AMessage> &msg);
+
private:
// Handles an OMX message. Returns true iff message was handled.
bool onOMXMessage(const sp<AMessage> &msg);
@@ -6502,6 +6504,59 @@
postFillThisBuffer(eligible);
}
+void ACodec::BaseState::setSurfaceParameters(const sp<AMessage> &msg) {
+ sp<AMessage> params;
+ CHECK(msg->findMessage("params", ¶ms));
+
+ status_t err = mCodec->setSurfaceParameters(params);
+ if (err != OK) {
+ ALOGE("[%s] Unable to set input surface parameters (err %d)",
+ mCodec->mComponentName.c_str(),
+ err);
+ return;
+ }
+
+ int64_t timeOffsetUs;
+ if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
+ params->removeEntryAt(params->findEntryByName(PARAMETER_KEY_OFFSET_TIME));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+
+ int64_t skipFramesBeforeUs;
+ if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
+ params->removeEntryAt(params->findEntryByName("skip-frames-before"));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+
+ int32_t dropInputFrames;
+ if (params->findInt32(PARAMETER_KEY_SUSPEND, &dropInputFrames)) {
+ params->removeEntryAt(params->findEntryByName(PARAMETER_KEY_SUSPEND));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+
+ int64_t stopTimeUs;
+ if (params->findInt64("stop-time-us", &stopTimeUs)) {
+ params->removeEntryAt(params->findEntryByName("stop-time-us"));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+}
+
bool ACodec::BaseState::onOMXFillBufferDone(
IOMX::buffer_id bufferID,
size_t rangeOffset, size_t rangeLength,
@@ -7368,6 +7423,13 @@
bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetParameters:
+ {
+ BaseState::setSurfaceParameters(msg);
+ if (msg->countEntries() > 0) {
+ mCodec->deferMessage(msg);
+ }
+ return true;
+ }
case kWhatShutdown:
{
mCodec->deferMessage(msg);
@@ -7444,6 +7506,13 @@
bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetParameters:
+ {
+ BaseState::setSurfaceParameters(msg);
+ if (msg->countEntries() > 0) {
+ mCodec->deferMessage(msg);
+ }
+ return true;
+ }
case kWhatShutdown:
{
mCodec->deferMessage(msg);
@@ -7723,27 +7792,7 @@
return handled;
}
-status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
- int32_t videoBitrate;
- if (params->findInt32("video-bitrate", &videoBitrate)) {
- OMX_VIDEO_CONFIG_BITRATETYPE configParams;
- InitOMXParams(&configParams);
- configParams.nPortIndex = kPortIndexOutput;
- configParams.nEncodeBitrate = videoBitrate;
-
- status_t err = mOMXNode->setConfig(
- OMX_IndexConfigVideoBitrate,
- &configParams,
- sizeof(configParams));
-
- if (err != OK) {
- ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
- videoBitrate, err);
-
- return err;
- }
- }
-
+status_t ACodec::setSurfaceParameters(const sp<AMessage> ¶ms) {
int64_t timeOffsetUs;
if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
if (mGraphicBufferSource == NULL) {
@@ -7831,9 +7880,41 @@
mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs);
}
+ return OK;
+}
+
+status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
+ status_t err;
+
+ int32_t videoBitrate;
+ if (params->findInt32("video-bitrate", &videoBitrate)) {
+ OMX_VIDEO_CONFIG_BITRATETYPE configParams;
+ InitOMXParams(&configParams);
+ configParams.nPortIndex = kPortIndexOutput;
+ configParams.nEncodeBitrate = videoBitrate;
+
+ err = mOMXNode->setConfig(
+ OMX_IndexConfigVideoBitrate,
+ &configParams,
+ sizeof(configParams));
+
+ if (err != OK) {
+ ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
+ videoBitrate, err);
+
+ return err;
+ }
+ }
+
+ err = setSurfaceParameters(params);
+ if (err != OK) {
+ ALOGE("Failed to set input surface parameters (err %d)", err);
+ return err;
+ }
+
int32_t tmp;
if (params->findInt32("request-sync", &tmp)) {
- status_t err = requestIDRFrame();
+ err = requestIDRFrame();
if (err != OK) {
ALOGE("Requesting a sync frame failed w/ err %d", err);
@@ -7848,7 +7929,7 @@
rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
}
if (rateFloat > 0) {
- status_t err = setOperatingRate(rateFloat, mIsVideo);
+ err = setOperatingRate(rateFloat, mIsVideo);
if (err != OK) {
ALOGI("Failed to set parameter 'operating-rate' (err %d)", err);
}
@@ -7857,7 +7938,7 @@
int32_t intraRefreshPeriod = 0;
if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
&& intraRefreshPeriod > 0) {
- status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
+ err = setIntraRefreshPeriod(intraRefreshPeriod, false);
if (err != OK) {
ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
mComponentName.c_str());
@@ -7867,7 +7948,7 @@
int32_t lowLatency = 0;
if (params->findInt32("low-latency", &lowLatency)) {
- status_t err = setLowLatency(lowLatency);
+ err = setLowLatency(lowLatency);
if (err != OK) {
return err;
}
@@ -7875,7 +7956,7 @@
int32_t latency = 0;
if (params->findInt32("latency", &latency) && latency > 0) {
- status_t err = setLatency(latency);
+ err = setLatency(latency);
if (err != OK) {
ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
mComponentName.c_str());
@@ -7887,7 +7968,7 @@
if (params->findInt32("audio-presentation-presentation-id", &presentationId)) {
int32_t programId = -1;
params->findInt32("audio-presentation-program-id", &programId);
- status_t err = setAudioPresentation(presentationId, programId);
+ err = setAudioPresentation(presentationId, programId);
if (err != OK) {
ALOGI("[%s] failed setAudioPresentation. Failure is fine since this key is optional",
mComponentName.c_str());
@@ -7960,7 +8041,7 @@
{
int32_t tunnelPeek = 0;
if (params->findInt32(TUNNEL_PEEK_KEY, &tunnelPeek)) {
- status_t err = setTunnelPeek(tunnelPeek);
+ err = setTunnelPeek(tunnelPeek);
if (err != OK) {
return err;
}
@@ -7969,7 +8050,7 @@
{
int32_t tunnelPeekSetLegacy = 0;
if (params->findInt32(TUNNEL_PEEK_SET_LEGACY_KEY, &tunnelPeekSetLegacy)) {
- status_t err = setTunnelPeekLegacy(tunnelPeekSetLegacy);
+ err = setTunnelPeekLegacy(tunnelPeekSetLegacy);
if (err != OK) {
return err;
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 386b790..89ebe7b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -31,7 +31,6 @@
#include <utils/Log.h>
#include <functional>
-#include <fcntl.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -556,6 +555,10 @@
mResetStatus = OK;
mPreAllocFirstTime = true;
mPrevAllTracksTotalMetaDataSizeEstimate = 0;
+ mIsFirstChunk = false;
+ mDone = false;
+ mThread = 0;
+ mDriftTimeUs = 0;
// Following variables only need to be set for the first recording session.
// And they will stay the same for all the recording sessions.
diff --git a/media/libstagefright/VideoFrameSchedulerBase.cpp b/media/libstagefright/VideoFrameSchedulerBase.cpp
index 0d1517b..965014c 100644
--- a/media/libstagefright/VideoFrameSchedulerBase.cpp
+++ b/media/libstagefright/VideoFrameSchedulerBase.cpp
@@ -451,7 +451,7 @@
return origRenderTime;
}
- ATRACE_INT("FRAME_VSYNCS", vsyncsForLastFrame);
+ ATRACE_INT64("FRAME_VSYNCS", vsyncsForLastFrame);
}
mLastVsyncTime = nextVsyncTime;
}
@@ -460,7 +460,7 @@
renderTime -= (renderTime - mVsyncTime) % mVsyncPeriod;
renderTime += mVsyncPeriod / 2;
ALOGV("adjusting render: %lld => %lld", (long long)origRenderTime, (long long)renderTime);
- ATRACE_INT("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
+ ATRACE_INT64("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
return renderTime;
}
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 38a4c1e..76b9633 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -601,6 +601,7 @@
status_t internalError = UNKNOWN_ERROR);
status_t requestIDRFrame();
+ status_t setSurfaceParameters(const sp<AMessage> ¶ms);
status_t setParameters(const sp<AMessage> ¶ms);
// set vendor extension parameters specified in params that are supported by the codec
diff --git a/media/libstagefright/tests/HEVC/AndroidTest.xml b/media/libstagefright/tests/HEVC/AndroidTest.xml
index ff850a2..00bb3e5 100644
--- a/media/libstagefright/tests/HEVC/AndroidTest.xml
+++ b/media/libstagefright/tests/HEVC/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push" value="HEVCUtilsUnitTest->/data/local/tmp/HEVCUtilsUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest.zip?unzip=true"
- value="/data/local/tmp/HEVCUtilsUnitTest/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="HEVCUtilsUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="HEVCUtilsUnitTest-1.0" />
+ <option name="dynamic-config-module" value="HEVCUtilsUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="HEVCUtilsUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/HEVCUtilsUnitTest/" />
+ <option name="native-test-flag" value="-P /sdcard/tests/HEVCUtilsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/libstagefright/tests/HEVC/DynamicConfig.xml b/media/libstagefright/tests/HEVC/DynamicConfig.xml
new file mode 100644
index 0000000..517449c
--- /dev/null
+++ b/media/libstagefright/tests/HEVC/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/tests/extractorFactory/AndroidTest.xml b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
index 3aa6392..f1d4201 100644
--- a/media/libstagefright/tests/extractorFactory/AndroidTest.xml
+++ b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ExtractorFactoryTest->/data/local/tmp/ExtractorFactoryTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
- value="/data/local/tmp/ExtractorFactoryTestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ExtractorFactoryTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="extractor-1.5" />
+ <option name="dynamic-config-module" value="ExtractorFactoryTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ExtractorFactoryTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/ExtractorFactoryTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/extractor-1.5/" />
</test>
</configuration>
diff --git a/media/libstagefright/tests/extractorFactory/DynamicConfig.xml b/media/libstagefright/tests/extractorFactory/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/tests/writer/AndroidTest.xml b/media/libstagefright/tests/writer/AndroidTest.xml
index cc890fe..0b0eb01 100644
--- a/media/libstagefright/tests/writer/AndroidTest.xml
+++ b/media/libstagefright/tests/writer/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="writerTest->/data/local/tmp/writerTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/WriterTestRes-1.1.zip?unzip=true"
- value="/data/local/tmp/WriterTestRes/" />
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="writerTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="WriterTestRes-1.2" />
+ <option name="dynamic-config-module" value="writerTest" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="writerTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/WriterTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/WriterTestRes-1.2/" />
<option name="native-test-flag" value="-C true" />
</test>
</configuration>
diff --git a/media/libstagefright/tests/writer/DynamicConfig.xml b/media/libstagefright/tests/writer/DynamicConfig.xml
new file mode 100644
index 0000000..e6dc502
--- /dev/null
+++ b/media/libstagefright/tests/writer/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/WriterTestRes-1.2.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/timedtext/test/AndroidTest.xml b/media/libstagefright/timedtext/test/AndroidTest.xml
index 3654e23..0d5d79f 100644
--- a/media/libstagefright/timedtext/test/AndroidTest.xml
+++ b/media/libstagefright/timedtext/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="TimedTextUnitTest->/data/local/tmp/TimedTextUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest.zip?unzip=true"
- value="/data/local/tmp/TimedTextUnitTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="TimedTextUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="TimedTextUnitTest-1.0" />
+ <option name="dynamic-config-module" value="TimedTextUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="TimedTextUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTestRes/" />
+ <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/libstagefright/timedtext/test/DynamicConfig.xml b/media/libstagefright/timedtext/test/DynamicConfig.xml
new file mode 100644
index 0000000..e36277e
--- /dev/null
+++ b/media/libstagefright/timedtext/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index afc873c..2f204f9 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -55,4 +55,5 @@
name: "media_codecs",
srcs: ["media_codecs.xsd"],
package_name: "media.codecs",
+ root_elements: ["MediaCodecs"],
}
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index ecfd85e..93111ec 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -169,7 +169,6 @@
public class XmlParser {
ctor public XmlParser();
- method public static media.codecs.Included readIncluded(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static media.codecs.MediaCodecs readMediaCodecs(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/media/module/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
index cff14ac..569420b 100644
--- a/media/module/bqhelper/GraphicBufferSource.cpp
+++ b/media/module/bqhelper/GraphicBufferSource.cpp
@@ -589,7 +589,7 @@
void GraphicBufferSource::onDataspaceChanged_l(
android_dataspace dataspace, android_pixel_format pixelFormat) {
- ALOGD("got buffer with new dataSpace #%x", dataspace);
+ ALOGD("got buffer with new dataSpace %#x", dataspace);
mLastDataspace = dataspace;
if (ColorUtils::convertDataSpaceToV0(dataspace)) {
diff --git a/media/module/codecs/amrnb/dec/test/AndroidTest.xml b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
index 1a9e678..539fa5c 100644
--- a/media/module/codecs/amrnb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
@@ -13,19 +13,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for Amr-nb Decoder unit test">
+<configuration description="Test module config for Amr-wb Decoder unit test">
<option name="test-suite-tag" value="AmrnbDecoderTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrnbDecoderTest->/data/local/tmp/AmrnbDecoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrnbDecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrnbDecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrnbDecoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrnbDecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrnbDecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrnbDecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrnbDecoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrnb/dec/test/DynamicConfig.xml b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..de81c48
--- /dev/null
+++ b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrnb/enc/test/AndroidTest.xml b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
index 9fe61b1..1509728 100644
--- a/media/module/codecs/amrnb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
@@ -13,19 +13,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for Amr-nb Encoder unit test">
+<configuration description="Test module config for Amr-wb Encoder unit test">
<option name="test-suite-tag" value="AmrnbEncoderTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrnbEncoderTest->/data/local/tmp/AmrnbEncoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrnbEncoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrnbEncoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrnbEncoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrnbEncoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrnbEncoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrnbEncoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrnbEncoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrnb/enc/test/DynamicConfig.xml b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..b22df38
--- /dev/null
+++ b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrwb/dec/test/AndroidTest.xml b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
index e211a1f..392df03 100644
--- a/media/module/codecs/amrwb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrwbDecoderTest->/data/local/tmp/AmrwbDecoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrwbDecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrwbDecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrwbDecoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrwbDecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrwbDecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrwbDecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrwbDecoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrwb/dec/test/DynamicConfig.xml b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..d41517f
--- /dev/null
+++ b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrwb/enc/test/AndroidTest.xml b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
index 46f147c..8822cb2 100644
--- a/media/module/codecs/amrwb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrwbEncoderTest->/data/local/tmp/AmrwbEncoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrwbEncoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrwbEncoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrwbEncoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrwbEncoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrwbEncoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrwbEncoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrwbEncoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrwb/enc/test/DynamicConfig.xml b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..1cf5bf5
--- /dev/null
+++ b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/flac/dec/test/AndroidTest.xml b/media/module/codecs/flac/dec/test/AndroidTest.xml
index bebba8e..015f728 100644
--- a/media/module/codecs/flac/dec/test/AndroidTest.xml
+++ b/media/module/codecs/flac/dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
- value="/data/local/tmp/FlacDecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="FlacDecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="FlacDecoder-1.0" />
+ <option name="dynamic-config-module" value="FlacDecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="FlacDecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/FlacDecoder-1.0/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/codecs/flac/dec/test/DynamicConfig.xml b/media/module/codecs/flac/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/module/codecs/flac/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
index 8bb4d1c..bd620d6 100755
--- a/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
+++ b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
@@ -19,14 +19,22 @@
<option name="cleanup" value="true" />
<option name="push" value="Mpeg4H263DecoderTest->/data/local/tmp/Mpeg4H263DecoderTest" />
<option name="append-bitness" value="true" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true"
- value="/data/local/tmp/Mpeg4H263DecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mpeg4H263DecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mpeg4H263DecoderTest-1.2" />
+ <option name="dynamic-config-module" value="Mpeg4H263DecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mpeg4H263DecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263DecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mpeg4H263DecoderTest-1.2/" />
</test>
</configuration>
diff --git a/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml b/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..5219361
--- /dev/null
+++ b/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.2.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
index 5218932..6b352b0 100644
--- a/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
+++ b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
- value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mpeg4H263EncoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mpeg4H263Encoder-1.1" />
+ <option name="dynamic-config-module" value="Mpeg4H263EncoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mpeg4H263EncoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mpeg4H263Encoder-1.1/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml b/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..ceb33ef
--- /dev/null
+++ b/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml
@@ -0,0 +1,21 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder-1.1.zip
+ </value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/mp3dec/test/AndroidTest.xml b/media/module/codecs/mp3dec/test/AndroidTest.xml
index 29952eb..d16f152 100644
--- a/media/module/codecs/mp3dec/test/AndroidTest.xml
+++ b/media/module/codecs/mp3dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="Mp3DecoderTest->/data/local/tmp/Mp3DecoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true"
- value="/data/local/tmp/Mp3DecoderTestRes/" />
+</target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mp3DecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mp3DecoderTest-1.3" />
+ <option name="dynamic-config-module" value="Mp3DecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mp3DecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mp3DecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mp3DecoderTest-1.3/" />
</test>
</configuration>
diff --git a/media/module/codecs/mp3dec/test/DynamicConfig.xml b/media/module/codecs/mp3dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..048940b
--- /dev/null
+++ b/media/module/codecs/mp3dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.3.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/esds/tests/AndroidTest.xml b/media/module/esds/tests/AndroidTest.xml
index a4fbc7f..87ca58c 100644
--- a/media/module/esds/tests/AndroidTest.xml
+++ b/media/module/esds/tests/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ESDSTest->/data/local/tmp/ESDSTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/ESDS/ESDSTestRes-1.0.zip?unzip=true"
- value="/data/local/tmp/ESDSTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ESDSTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="ESDSTestRes-1.1" />
+ <option name="dynamic-config-module" value="ESDSTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ESDSTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/ESDSTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/ESDSTestRes-1.1/" />
</test>
</configuration>
diff --git a/media/module/esds/tests/DynamicConfig.xml b/media/module/esds/tests/DynamicConfig.xml
new file mode 100644
index 0000000..9718dda
--- /dev/null
+++ b/media/module/esds/tests/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/ESDS/ESDSTestRes-1.1.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/extractors/mp3/VBRISeeker.cpp b/media/module/extractors/mp3/VBRISeeker.cpp
index ca51b88..a50754b 100644
--- a/media/module/extractors/mp3/VBRISeeker.cpp
+++ b/media/module/extractors/mp3/VBRISeeker.cpp
@@ -84,7 +84,7 @@
scale,
entrySize);
- if (entrySize > 4) {
+ if (entrySize < 1 || entrySize > 4) {
ALOGE("invalid VBRI entry size: %zu", entrySize);
return NULL;
}
@@ -122,16 +122,13 @@
off64_t offset = post_id3_pos;
for (size_t i = 0; i < numEntries; ++i) {
- uint32_t numBytes;
+ uint32_t numBytes = 0;
+ // entrySize is known to be [1..4]
switch (entrySize) {
case 1: numBytes = buffer[i]; break;
case 2: numBytes = U16_AT(buffer + 2 * i); break;
case 3: numBytes = U24_AT(buffer + 3 * i); break;
- default:
- {
- CHECK_EQ(entrySize, 4u);
- numBytes = U32_AT(buffer + 4 * i); break;
- }
+ case 4: numBytes = U32_AT(buffer + 4 * i); break;
}
numBytes *= scale;
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 1d88785..eaca75c 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -26,7 +26,6 @@
#include <stdlib.h>
#include <string.h>
-#include <log/log.h>
#include <utils/Log.h>
#include "AC4Parser.h"
diff --git a/media/module/extractors/tests/AndroidTest.xml b/media/module/extractors/tests/AndroidTest.xml
index fc8152c..22669df 100644
--- a/media/module/extractors/tests/AndroidTest.xml
+++ b/media/module/extractors/tests/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ExtractorUnitTest->/data/local/tmp/ExtractorUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true"
- value="/data/local/tmp/ExtractorUnitTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ExtractorUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="extractor-1.5" />
+ <option name="dynamic-config-module" value="ExtractorUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ExtractorUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/ExtractorUnitTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/extractor-1.5/" />
</test>
</configuration>
diff --git a/media/module/extractors/tests/DynamicConfig.xml b/media/module/extractors/tests/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/module/extractors/tests/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/foundation/tests/AVCUtils/AndroidTest.xml b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
index 6a088a8..e30bfbf 100644
--- a/media/module/foundation/tests/AVCUtils/AndroidTest.xml
+++ b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push" value="AVCUtilsUnitTest->/data/local/tmp/AVCUtilsUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.zip?unzip=true"
- value="/data/local/tmp/AVCUtilsUnitTest/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AVCUtilsUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AVCUtilsUnitTest-1.0" />
+ <option name="dynamic-config-module" value="AVCUtilsUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AVCUtilsUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AVCUtilsUnitTest/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AVCUtilsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/foundation/tests/AVCUtils/DynamicConfig.xml b/media/module/foundation/tests/AVCUtils/DynamicConfig.xml
new file mode 100644
index 0000000..e5b8bad
--- /dev/null
+++ b/media/module/foundation/tests/AVCUtils/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value> https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/foundation/tests/OpusHeader/AndroidTest.xml b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
index afee16a..4aa4cd2 100644
--- a/media/module/foundation/tests/OpusHeader/AndroidTest.xml
+++ b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="OpusHeaderTest->/data/local/tmp/OpusHeaderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true"
- value="/data/local/tmp/OpusHeaderTestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="OpusHeaderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="OpusHeader-1.0" />
+ <option name="dynamic-config-module" value="OpusHeaderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="OpusHeaderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/OpusHeaderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/OpusHeader-1.0/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/foundation/tests/OpusHeader/DynamicConfig.xml b/media/module/foundation/tests/OpusHeader/DynamicConfig.xml
new file mode 100644
index 0000000..ebac328
--- /dev/null
+++ b/media/module/foundation/tests/OpusHeader/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/id3/test/AndroidTest.xml b/media/module/id3/test/AndroidTest.xml
index 50f9253..b169994 100644
--- a/media/module/id3/test/AndroidTest.xml
+++ b/media/module/id3/test/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ID3Test->/data/local/tmp/ID3Test" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true"
- value="/data/local/tmp/ID3TestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ID3Test" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="ID3TestRes-1.3" />
+ <option name="dynamic-config-module" value="ID3Test" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ID3Test" />
- <option name="native-test-flag" value="-P /data/local/tmp/ID3TestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/ID3TestRes-1.3/" />
</test>
</configuration>
diff --git a/media/module/id3/test/DynamicConfig.xml b/media/module/id3/test/DynamicConfig.xml
new file mode 100644
index 0000000..5ae4fcd
--- /dev/null
+++ b/media/module/id3/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.3.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/metadatautils/test/AndroidTest.xml b/media/module/metadatautils/test/AndroidTest.xml
index d6497f3..ce8c4d6 100644
--- a/media/module/metadatautils/test/AndroidTest.xml
+++ b/media/module/metadatautils/test/AndroidTest.xml
@@ -18,13 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push" value="MetaDataUtilsTest->/data/local/tmp/MetaDataUtilsTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/metadatautils/MetaDataUtilsTestRes-1.0.zip?unzip=true"
- value="/data/local/tmp/MetaDataUtilsTestRes/" />
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="MetaDataUtilsTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="MetaDataUtilsTest-1.1" />
+ <option name="dynamic-config-module" value="MetaDataUtilsTest" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="MetaDataUtilsTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/MetaDataUtilsTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/MetaDataUtilsTest-1.1/" />
</test>
</configuration>
diff --git a/media/module/metadatautils/test/DynamicConfig.xml b/media/module/metadatautils/test/DynamicConfig.xml
new file mode 100644
index 0000000..9d80bf3
--- /dev/null
+++ b/media/module/metadatautils/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/metadatautils/MetaDataUtilsTestRes-1.1.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/mpeg2ts/test/AndroidTest.xml b/media/module/mpeg2ts/test/AndroidTest.xml
index ac1294d..836c9f8 100644
--- a/media/module/mpeg2ts/test/AndroidTest.xml
+++ b/media/module/mpeg2ts/test/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="Mpeg2tsUnitTest->/data/local/tmp/Mpeg2tsUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true"
- value="/data/local/tmp/Mpeg2tsUnitTestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mpeg2tsUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mpeg2tsUnitTest-1.0" />
+ <option name="dynamic-config-module" value="Mpeg2tsUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mpeg2tsUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mpeg2tsUnitTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mpeg2tsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/mpeg2ts/test/DynamicConfig.xml b/media/module/mpeg2ts/test/DynamicConfig.xml
new file mode 100644
index 0000000..017a3c6
--- /dev/null
+++ b/media/module/mpeg2ts/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index f1797e6..7af2a90 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -180,6 +180,7 @@
"av-types-aidl-cpp",
"effect-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libaudioflinger_timing",
"libaudiofoundation",
"libaudiohal",
"libaudioprocessing",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0f5021b..1634051 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -111,6 +111,7 @@
using media::IEffectClient;
using media::audio::common::AudioMMapPolicyInfo;
using media::audio::common::AudioMMapPolicyType;
+using media::audio::common::AudioMode;
using android::content::AttributionSourceState;
using android::detail::AudioHalVersionInfo;
@@ -235,6 +236,7 @@
BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
BINDER_METHOD_ENTRY(isBluetoothVariableLatencyEnabled) \
BINDER_METHOD_ENTRY(supportsBluetoothVariableLatency) \
+BINDER_METHOD_ENTRY(getAudioPolicyConfig) \
// singleton for Binder Method Statistics for IAudioFlinger
static auto& getIAudioFlingerStatistics() {
@@ -1234,18 +1236,19 @@
}
// Look for sync events awaiting for a session to be used.
- for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
- if (mPendingSyncEvents[i]->triggerSession() == sessionId) {
- if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
+ for (auto it = mPendingSyncEvents.begin(); it != mPendingSyncEvents.end();) {
+ if ((*it)->triggerSession() == sessionId) {
+ if (thread->isValidSyncEvent(*it)) {
if (lStatus == NO_ERROR) {
- (void) track->setSyncEvent(mPendingSyncEvents[i]);
+ (void) track->setSyncEvent(*it);
} else {
- mPendingSyncEvents[i]->cancel();
+ (*it)->cancel();
}
- mPendingSyncEvents.removeAt(i);
- i--;
+ it = mPendingSyncEvents.erase(it);
+ continue;
}
}
+ ++it;
}
if ((output.flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
setAudioHwSyncForSession_l(thread, sessionId);
@@ -2538,6 +2541,47 @@
// ----------------------------------------------------------------------------
+status_t AudioFlinger::getAudioPolicyConfig(media::AudioPolicyConfig *config)
+{
+ if (config == nullptr) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoMutex lock(mHardwareLock);
+ RETURN_STATUS_IF_ERROR(
+ mDevicesFactoryHal->getSurroundSoundConfig(&config->surroundSoundConfig));
+ RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getEngineConfig(&config->engineConfig));
+ std::vector<std::string> hwModuleNames;
+ RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getDeviceNames(&hwModuleNames));
+ std::set<AudioMode> allSupportedModes;
+ for (const auto& name : hwModuleNames) {
+ AudioHwDevice* module = loadHwModule_l(name.c_str());
+ if (module == nullptr) continue;
+ media::AudioHwModule aidlModule;
+ if (module->hwDevice()->getAudioPorts(&aidlModule.ports) == OK &&
+ module->hwDevice()->getAudioRoutes(&aidlModule.routes) == OK) {
+ aidlModule.handle = module->handle();
+ aidlModule.name = module->moduleName();
+ config->modules.push_back(std::move(aidlModule));
+ }
+ std::vector<AudioMode> supportedModes;
+ if (module->hwDevice()->getSupportedModes(&supportedModes) == OK) {
+ allSupportedModes.insert(supportedModes.begin(), supportedModes.end());
+ }
+ }
+ if (!allSupportedModes.empty()) {
+ config->supportedModes.insert(config->supportedModes.end(),
+ allSupportedModes.begin(), allSupportedModes.end());
+ } else {
+ ALOGW("%s: The HAL does not provide telephony functionality", __func__);
+ config->supportedModes = { media::audio::common::AudioMode::NORMAL,
+ media::audio::common::AudioMode::RINGTONE,
+ media::audio::common::AudioMode::IN_CALL,
+ media::audio::common::AudioMode::IN_COMMUNICATION };
+ }
+ return OK;
+}
+
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
if (name == NULL) {
@@ -2548,16 +2592,17 @@
}
Mutex::Autolock _l(mLock);
AutoMutex lock(mHardwareLock);
- return loadHwModule_l(name);
+ AudioHwDevice* module = loadHwModule_l(name);
+ return module != nullptr ? module->handle() : AUDIO_MODULE_HANDLE_NONE;
}
// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
-audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
+AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
{
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
ALOGW("loadHwModule() module %s already loaded", name);
- return mAudioHwDevs.keyAt(i);
+ return mAudioHwDevs.valueAt(i);
}
}
@@ -2566,7 +2611,7 @@
int rc = mDevicesFactoryHal->openDevice(name, &dev);
if (rc) {
ALOGE("loadHwModule() error %d loading module %s", rc, name);
- return AUDIO_MODULE_HANDLE_NONE;
+ return nullptr;
}
mHardwareStatus = AUDIO_HW_INIT;
@@ -2574,7 +2619,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
if (rc) {
ALOGE("loadHwModule() init check error %d for module %s", rc, name);
- return AUDIO_MODULE_HANDLE_NONE;
+ return nullptr;
}
// Check and cache this HAL's level of support for master mute and master
@@ -2648,8 +2693,7 @@
ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
- return handle;
-
+ return audioDevice;
}
// ----------------------------------------------------------------------------
@@ -2898,14 +2942,6 @@
return nullptr;
}
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
- ALOGE("openOutput_l() cannot create spatializer thread "
- "without #define MULTICHANNEL_EFFECT_CHAIN");
- return nullptr;
- }
-#endif
-
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
// FOR TESTING ONLY:
@@ -3876,15 +3912,16 @@
track->setTeePatches(std::move(teePatches));
}
-sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
+sp<audioflinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
- sync_event_callback_t callBack,
+ const audioflinger::SyncEventCallback& callBack,
const wp<RefBase>& cookie)
{
Mutex::Autolock _l(mLock);
- sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
+ auto event = sp<audioflinger::SyncEvent>::make(
+ type, triggerSession, listenerSession, callBack, cookie);
status_t playStatus = NAME_NOT_FOUND;
status_t recStatus = NAME_NOT_FOUND;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -3900,7 +3937,7 @@
}
}
if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
- mPendingSyncEvents.add(event);
+ mPendingSyncEvents.emplace_back(event);
} else {
ALOGV("createSyncEvent() invalid event %d", event->type());
event.clear();
@@ -4648,6 +4685,7 @@
case TransactionCode::SET_DEVICE_CONNECTED_STATE:
case TransactionCode::SET_REQUESTED_LATENCY_MODE:
case TransactionCode::GET_SUPPORTED_LATENCY_MODES:
+ case TransactionCode::GET_AUDIO_POLICY_CONFIG:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
// return status only for non void methods
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c2493ec..023f130 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -84,6 +84,10 @@
#include <audio_utils/SimpleLog.h>
#include <audio_utils/TimestampVerifier.h>
+#include <timing/MonotonicFrameCounter.h>
+#include <timing/SyncEvent.h>
+#include <timing/SynchronizedRecordState.h>
+
#include "FastCapture.h"
#include "FastMixer.h"
#include <media/nbaio/NBAIO.h>
@@ -131,6 +135,7 @@
class AudioFlinger : public AudioFlingerServerAdapter::Delegate
{
+ friend class sp<AudioFlinger>;
public:
static void instantiate() ANDROID_API;
@@ -308,6 +313,8 @@
virtual status_t supportsBluetoothVariableLatency(bool* support);
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+
status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
const std::function<status_t()>& delegate) override;
@@ -369,47 +376,10 @@
static inline std::atomic<AudioFlinger *> gAudioFlinger = nullptr;
- class SyncEvent;
-
- typedef void (*sync_event_callback_t)(const wp<SyncEvent>& event) ;
-
- class SyncEvent : public RefBase {
- public:
- SyncEvent(AudioSystem::sync_event_t type,
- audio_session_t triggerSession,
- audio_session_t listenerSession,
- sync_event_callback_t callBack,
- const wp<RefBase>& cookie)
- : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
- mCallback(callBack), mCookie(cookie)
- {}
-
- virtual ~SyncEvent() {}
-
- void trigger() {
- Mutex::Autolock _l(mLock);
- if (mCallback) mCallback(wp<SyncEvent>(this));
- }
- bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
- void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
- AudioSystem::sync_event_t type() const { return mType; }
- audio_session_t triggerSession() const { return mTriggerSession; }
- audio_session_t listenerSession() const { return mListenerSession; }
- wp<RefBase> cookie() const { return mCookie; }
-
- private:
- const AudioSystem::sync_event_t mType;
- const audio_session_t mTriggerSession;
- const audio_session_t mListenerSession;
- sync_event_callback_t mCallback;
- const wp<RefBase> mCookie;
- mutable Mutex mLock;
- };
-
- sp<SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+ sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
- sync_event_callback_t callBack,
+ const audioflinger::SyncEventCallback& callBack,
const wp<RefBase>& cookie);
bool btNrecIsOff() const { return mBtNrecIsOff.load(); }
@@ -626,13 +596,6 @@
};
// --- PlaybackThread ---
-#ifdef FLOAT_EFFECT_CHAIN
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
-using effect_buffer_t = float;
-#else
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_16_BIT
-using effect_buffer_t = int16_t;
-#endif
#include "Threads.h"
@@ -968,10 +931,10 @@
float masterVolume_l() const;
float getMasterBalance_l() const;
bool masterMute_l() const;
- audio_module_handle_t loadHwModule_l(const char *name);
+ AudioHwDevice* loadHwModule_l(const char *name);
- Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session
- // to be created
+ // sync events awaiting for a session to be created.
+ std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
// Effect chains without a valid thread
DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index ede8e3f..845697a 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -41,15 +41,4 @@
// uncomment to log CPU statistics every n wall clock seconds
//#define DEBUG_CPU_USAGE 10
-// define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable)
-#define FLOAT_EFFECT_CHAIN
-
-#ifdef FLOAT_EFFECT_CHAIN
-// define FLOAT_AUX to process aux effect buffers in float (FLOAT_EFFECT_CHAIN must be defined)
-#define FLOAT_AUX
-
-// define MULTICHANNEL_EFFECT_CHAIN to allow multichannel effects (FLOAT_EFFECT_CHAIN defined)
-#define MULTICHANNEL_EFFECT_CHAIN
-#endif
-
#endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index e912bff..1c46ddd 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -572,9 +572,7 @@
mOffloaded(false),
mAddedToHal(false),
mIsOutput(false)
-#ifdef FLOAT_EFFECT_CHAIN
, mSupportsFloat(false)
-#endif
{
ALOGV("Constructor %p pinned %d", this, pinned);
int lStatus;
@@ -693,31 +691,16 @@
mConfig.inputCfg.buffer.frameCount,
mConfig.outputCfg.buffer.frameCount);
const auto accumulateInputToOutput = [this, safeInputOutputSampleCount]() {
-#ifdef FLOAT_EFFECT_CHAIN
accumulate_float(
mConfig.outputCfg.buffer.f32,
mConfig.inputCfg.buffer.f32,
safeInputOutputSampleCount);
-#else
- accumulate_i16(
- mConfig.outputCfg.buffer.s16,
- mConfig.inputCfg.buffer.s16,
- safeInputOutputSampleCount);
-#endif
};
const auto copyInputToOutput = [this, safeInputOutputSampleCount]() {
-#ifdef FLOAT_EFFECT_CHAIN
memcpy(
mConfig.outputCfg.buffer.f32,
mConfig.inputCfg.buffer.f32,
safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.f32));
-
-#else
- memcpy(
- mConfig.outputCfg.buffer.s16,
- mConfig.inputCfg.buffer.s16,
- safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.s16));
-#endif
};
if (isProcessEnabled()) {
@@ -726,35 +709,14 @@
if (auxType) {
// We overwrite the aux input buffer here and clear after processing.
// aux input is always mono.
-#ifdef FLOAT_EFFECT_CHAIN
- if (mSupportsFloat) {
-#ifndef FLOAT_AUX
- // Do in-place float conversion for auxiliary effect input buffer.
- static_assert(sizeof(float) <= sizeof(int32_t),
- "in-place conversion requires sizeof(float) <= sizeof(int32_t)");
- memcpy_to_float_from_q4_27(
- mConfig.inputCfg.buffer.f32,
- mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount);
-#endif // !FLOAT_AUX
- } else
-#endif // FLOAT_EFFECT_CHAIN
- {
-#ifdef FLOAT_AUX
+ if (!mSupportsFloat) {
memcpy_to_i16_from_float(
mConfig.inputCfg.buffer.s16,
mConfig.inputCfg.buffer.f32,
mConfig.inputCfg.buffer.frameCount);
-#else
- memcpy_to_i16_from_q4_27(
- mConfig.inputCfg.buffer.s16,
- mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount);
-#endif
}
}
-#ifdef FLOAT_EFFECT_CHAIN
sp<EffectBufferHalInterface> inBuffer = mInBuffer;
sp<EffectBufferHalInterface> outBuffer = mOutBuffer;
@@ -801,9 +763,7 @@
outBuffer = mOutConversionBuffer;
}
}
-#endif
ret = mEffectInterface->process();
-#ifdef FLOAT_EFFECT_CHAIN
if (!mSupportsFloat) { // convert output int16_t back to float.
sp<EffectBufferHalInterface> target =
mOutChannelCountRequested != outChannelCount
@@ -820,11 +780,8 @@
sizeof(float),
sizeof(float) * outChannelCount * mConfig.outputCfg.buffer.frameCount);
}
-#endif
} else {
-#ifdef FLOAT_EFFECT_CHAIN
data_bypass:
-#endif
if (!auxType /* aux effects do not require data bypass */
&& mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
@@ -843,13 +800,8 @@
// clear auxiliary effect input buffer for next accumulation
if (auxType) {
-#ifdef FLOAT_AUX
const size_t size =
mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(float);
-#else
- const size_t size =
- mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t);
-#endif
memset(mConfig.inputCfg.buffer.raw, 0, size);
}
} else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
@@ -904,23 +856,6 @@
ALOGV("Overriding auxiliary effect input channels %#x as MONO",
mConfig.inputCfg.channels);
}
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
- mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- ALOGV("Overriding auxiliary effect output channels %#x as STEREO",
- mConfig.outputCfg.channels);
- }
-#endif
- } else {
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- // TODO: Update this logic when multichannel effects are implemented.
- // For offloaded tracks consider mono output as stereo for proper effect initialization
- if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
- mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- ALOGV("Overriding effect input and output as STEREO");
- }
-#endif
}
if (isHapticGenerator()) {
audio_channel_mask_t hapticChannelMask = callback->hapticChannelMask();
@@ -932,8 +867,8 @@
mOutChannelCountRequested =
audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
- mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
- mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
+ mConfig.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+ mConfig.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
// Don't use sample rate for thread if effect isn't offloadable.
if (callback->isOffloadOrDirect() && !isOffloaded()) {
@@ -981,7 +916,6 @@
status = cmdStatus;
}
-#ifdef MULTICHANNEL_EFFECT_CHAIN
if (status != NO_ERROR &&
mIsOutput &&
(mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
@@ -1006,9 +940,7 @@
status = cmdStatus;
}
}
-#endif
-#ifdef FLOAT_EFFECT_CHAIN
if (status == NO_ERROR) {
mSupportsFloat = true;
}
@@ -1033,7 +965,6 @@
ALOGE("%s failed %d with int16_t (as well as float)", __func__, status);
}
}
-#endif
if (status == NO_ERROR) {
// Establish Buffer strategy
@@ -1347,7 +1278,6 @@
mInBuffer = buffer;
mEffectInterface->setInBuffer(buffer);
-#ifdef FLOAT_EFFECT_CHAIN
// aux effects do in place conversion to float - we don't allocate mInConversionBuffer.
// Theoretically insert effects can also do in-place conversions (destroying
// the original buffer) when the output buffer is identical to the input buffer,
@@ -1379,7 +1309,6 @@
ALOGE("%s cannot create mInConversionBuffer", __func__);
}
}
-#endif
}
void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
@@ -1395,7 +1324,6 @@
mOutBuffer = buffer;
mEffectInterface->setOutBuffer(buffer);
-#ifdef FLOAT_EFFECT_CHAIN
// Note: Any effect that does not accumulate does not need mOutConversionBuffer and
// can do in-place conversion from int16_t to float. We don't optimize here.
const uint32_t outChannelCount =
@@ -1423,7 +1351,6 @@
ALOGE("%s cannot create mOutConversionBuffer", __func__);
}
}
-#endif
}
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
@@ -1719,15 +1646,12 @@
mConfig.outputCfg.format,
formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
-#ifdef FLOAT_EFFECT_CHAIN
-
result.appendFormat("\t\t- HAL buffers:\n"
"\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
dumpInOutBuffer(true /* isInput */, mInBuffer).c_str(),
dumpInOutBuffer(true /* isInput */, mInConversionBuffer).c_str(),
dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
-#endif
write(fd, result.string(), result.length());
@@ -2253,7 +2177,7 @@
if (mInBuffer == NULL) {
return;
}
- const size_t frameSize = audio_bytes_per_sample(EFFECT_BUFFER_FORMAT)
+ const size_t frameSize = audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT)
* mEffectCallback->inChannelCount(mEffects[0]->id());
memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
@@ -2354,13 +2278,9 @@
// calling the process in effect engine
size_t numSamples = mEffectCallback->frameCount();
sp<EffectBufferHalInterface> halBuffer;
-#ifdef FLOAT_EFFECT_CHAIN
+
status_t result = mEffectCallback->allocateHalBuffer(
numSamples * sizeof(float), &halBuffer);
-#else
- status_t result = mEffectCallback->allocateHalBuffer(
- numSamples * sizeof(int32_t), &halBuffer);
-#endif
if (result != OK) return result;
effect->configure();
@@ -3355,8 +3275,18 @@
ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
__func__, port->type, port->ext.device.type,
port->ext.device.address, port->id, patch.isSoftware());
- if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType
- || port->ext.device.address != mDevice.address()) {
+ if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType ||
+ port->ext.device.address != mDevice.address()) {
+ return NAME_NOT_FOUND;
+ }
+ if (((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) &&
+ (audio_port_config_has_input_direction(port))) {
+ ALOGI("%s don't create postprocessing effect on record port", __func__);
+ return NAME_NOT_FOUND;
+ }
+ if (((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) &&
+ (!audio_port_config_has_input_direction(port))) {
+ ALOGI("%s don't create preprocessing effect on playback port", __func__);
return NAME_NOT_FOUND;
}
status_t status = NAME_NOT_FOUND;
@@ -3408,6 +3338,7 @@
} else {
status = BAD_VALUE;
}
+
if (status == NO_ERROR || status == ALREADY_EXISTS) {
Status bs;
if (isEnabled()) {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index bad86bc..e1a76fc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -322,13 +322,11 @@
bool mAddedToHal; // effect has been added to the audio HAL
bool mIsOutput; // direction of the AF thread
-#ifdef FLOAT_EFFECT_CHAIN
bool mSupportsFloat; // effect supports float processing
sp<EffectBufferHalInterface> mInConversionBuffer; // Buffers for HAL conversion if needed.
sp<EffectBufferHalInterface> mOutConversionBuffer;
uint32_t mInChannelCountRequested;
uint32_t mOutChannelCountRequested;
-#endif
class AutoLockReentrant {
public:
@@ -493,14 +491,14 @@
void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
mInBuffer = buffer;
}
- effect_buffer_t *inBuffer() const {
- return mInBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mInBuffer->ptr()) : NULL;
+ float *inBuffer() const {
+ return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
}
void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
mOutBuffer = buffer;
}
- effect_buffer_t *outBuffer() const {
- return mOutBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mOutBuffer->ptr()) : NULL;
+ float *outBuffer() const {
+ return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
}
void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 33983d7..78da621 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -116,8 +116,8 @@
status_t attachAuxEffect(int EffectId);
void setAuxBuffer(int EffectId, int32_t *buffer);
int32_t *auxBuffer() const { return mAuxBuffer; }
- void setMainBuffer(effect_buffer_t *buffer) { mMainBuffer = buffer; }
- effect_buffer_t *mainBuffer() const { return mMainBuffer; }
+ void setMainBuffer(float *buffer) { mMainBuffer = buffer; }
+ float *mainBuffer() const { return mMainBuffer; }
int auxEffectId() const { return mAuxEffectId; }
virtual status_t getTimestamp(AudioTimestamp& timestamp);
void signal();
@@ -131,7 +131,7 @@
// implement FastMixerState::VolumeProvider interface
virtual gain_minifloat_packed_t getVolumeLR();
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
virtual bool isFastTrack() const { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
@@ -283,7 +283,7 @@
bool mResetDone;
const audio_stream_type_t mStreamType;
- effect_buffer_t *mMainBuffer;
+ float *mMainBuffer;
int32_t *mAuxBuffer;
int mAuxEffectId;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index f0a5f76..d91a210 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -58,7 +58,7 @@
void appendDumpHeader(String8& result);
void appendDump(String8& result, bool active);
- void handleSyncStartEvent(const sp<SyncEvent>& event);
+ void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event);
void clearSyncStartEvent();
void updateTrackFrameInfo(int64_t trackFramesReleased,
@@ -107,12 +107,10 @@
// sync event triggering actual audio capture. Frames read before this event will
// be dropped and therefore not read by the application.
- sp<SyncEvent> mSyncStartEvent;
+ sp<audioflinger::SyncEvent> mSyncStartEvent;
- // number of captured frames to drop after the start sync event has been received.
- // when < 0, maximum frames to drop before starting capture even if sync event is
- // not received
- ssize_t mFramesToDrop;
+ audioflinger::SynchronizedRecordState
+ mSynchronizedRecordState{mSampleRate}; // sampleRate defined in base
// used by resampler to find source frames
ResamplerBufferProvider *mResamplerBufferProvider;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0f2717a..8b9eab0 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1404,15 +1404,6 @@
switch (mType) {
case MIXER: {
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- // Reject any effect on mixer multichannel sinks.
- // TODO: fix both format and multichannel issues with effects.
- if (mChannelCount != FCC_2) {
- ALOGW("%s: effect %s for multichannel(%d) on MIXER thread %s",
- __func__, desc->name, mChannelCount, mThreadName);
- return BAD_VALUE;
- }
-#endif
audio_output_flags_t flags = mOutput->flags;
if (hasFastMixer() || (flags & AUDIO_OUTPUT_FLAG_FAST)) {
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
@@ -1465,15 +1456,6 @@
__func__, desc->name, mThreadName);
return BAD_VALUE;
case DUPLICATING:
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- // Reject any effect on mixer multichannel sinks.
- // TODO: fix both format and multichannel issues with effects.
- if (mChannelCount != FCC_2) {
- ALOGW("%s: effect %s for multichannel(%d) on DUPLICATING thread %s",
- __func__, desc->name, mChannelCount, mThreadName);
- return BAD_VALUE;
- }
-#endif
if (audio_is_global_session(sessionId)) {
ALOGW("%s: global effect %s on DUPLICATING thread %s",
__func__, desc->name, mThreadName);
@@ -3124,7 +3106,7 @@
free(mEffectBuffer);
mEffectBuffer = NULL;
if (mEffectBufferEnabled) {
- mEffectBufferFormat = EFFECT_BUFFER_FORMAT;
+ mEffectBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
mEffectBufferSize = mNormalFrameCount * mixerChannelCount
* audio_bytes_per_sample(mEffectBufferFormat);
(void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
@@ -3278,7 +3260,7 @@
return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
}
-status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<audioflinger::SyncEvent>& event)
{
if (!isValidSyncEvent(event)) {
return BAD_VALUE;
@@ -3297,7 +3279,8 @@
return NAME_NOT_FOUND;
}
-bool AudioFlinger::PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event) const
+bool AudioFlinger::PlaybackThread::isValidSyncEvent(
+ const sp<audioflinger::SyncEvent>& event) const
{
return event->type() == AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
}
@@ -3517,7 +3500,7 @@
{
audio_session_t session = chain->sessionId();
sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
- effect_buffer_t *buffer = nullptr; // only used for non global sessions
+ float *buffer = nullptr; // only used for non global sessions
if (mType == SPATIALIZER) {
if (!audio_is_global_session(session)) {
@@ -3535,7 +3518,7 @@
size_t numSamples = mNormalFrameCount
* (audio_channel_count_from_out_mask(channelMask) + mHapticChannelCount);
status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
- numSamples * sizeof(effect_buffer_t),
+ numSamples * sizeof(float),
&halInBuffer);
if (result != OK) return result;
@@ -3545,11 +3528,8 @@
&halOutBuffer);
if (result != OK) return result;
-#ifdef FLOAT_EFFECT_CHAIN
buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
-#else
- buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
-#endif
+
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
} else {
@@ -3577,7 +3557,7 @@
halOutBuffer = halInBuffer;
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
if (!audio_is_global_session(session)) {
- buffer = halInBuffer ? reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData())
+ buffer = halInBuffer ? reinterpret_cast<float*>(halInBuffer->externalData())
: buffer;
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
@@ -3586,14 +3566,11 @@
* (audio_channel_count_from_out_mask(mMixerChannelMask)
+ mHapticChannelCount);
const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
- numSamples * sizeof(effect_buffer_t),
+ numSamples * sizeof(float),
&halInBuffer);
if (allocateStatus != OK) return allocateStatus;
-#ifdef FLOAT_EFFECT_CHAIN
+
buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
-#else
- buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
-#endif
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
}
@@ -3677,7 +3654,7 @@
for (size_t j = 0; j < mTracks.size(); ++j) {
sp<Track> track = mTracks[j];
if (session == track->sessionId()) {
- track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
+ track->setMainBuffer(reinterpret_cast<float*>(mSinkBuffer));
chain->decTrackCnt();
}
}
@@ -4082,12 +4059,12 @@
const size_t audioBufferSize = mNormalFrameCount
* audio_bytes_per_frame(hapticSessionChannelCount,
- EFFECT_BUFFER_FORMAT);
+ AUDIO_FORMAT_PCM_FLOAT);
memcpy_by_audio_format(
(uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
- EFFECT_BUFFER_FORMAT,
+ AUDIO_FORMAT_PCM_FLOAT,
(const uint8_t*)effectChains[i]->inBuffer() + audioBufferSize,
- EFFECT_BUFFER_FORMAT, mNormalFrameCount * mHapticChannelCount);
+ AUDIO_FORMAT_PCM_FLOAT, mNormalFrameCount * mHapticChannelCount);
}
}
}
@@ -5730,7 +5707,7 @@
mAudioMixer->setParameter(
trackId,
AudioMixer::TRACK,
- AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
+ AudioMixer::MIXER_FORMAT, (void *)AUDIO_FORMAT_PCM_FLOAT);
mAudioMixer->setParameter(
trackId,
AudioMixer::TRACK,
@@ -6191,8 +6168,18 @@
// Ensure volumeshaper state always advances even when muted.
const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
- const auto [shaperVolume, shaperActive] = track->getVolumeHandler()->getVolume(
- proxy->framesReleased());
+
+ const size_t framesReleased = proxy->framesReleased();
+ const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+
+ ALOGV("%s: Direct/Offload bufferConsumed:%zu timestamp frames:%lld time:%lld",
+ __func__, framesReleased, (long long)frames, (long long)time);
+
+ const int64_t volumeShaperFrames =
+ mMonotonicFrameCounter.updateAndGetMonotonicFrameCount(frames, time);
+ const auto [shaperVolume, shaperActive] =
+ track->getVolumeHandler()->getVolume(volumeShaperFrames);
mVolumeShaperActive = shaperActive;
if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
@@ -6668,6 +6655,7 @@
mFlushPending = false;
mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
mTimestamp.clear();
+ mMonotonicFrameCounter.onFlush();
}
int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
@@ -8211,7 +8199,11 @@
overrun = OVERRUN_FALSE;
}
- if (activeTrack->mFramesToDrop == 0) {
+ // MediaSyncEvent handling: Synchronize AudioRecord to AudioTrack completion.
+ const ssize_t framesToDrop =
+ activeTrack->mSynchronizedRecordState.updateRecordFrames(framesOut);
+ if (framesToDrop == 0) {
+ // no sync event, process normally, otherwise ignore.
if (framesOut > 0) {
activeTrack->mSink.frameCount = framesOut;
// Sanitize before releasing if the track has no access to the source data
@@ -8221,28 +8213,7 @@
}
activeTrack->releaseBuffer(&activeTrack->mSink);
}
- } else {
- // FIXME could do a partial drop of framesOut
- if (activeTrack->mFramesToDrop > 0) {
- activeTrack->mFramesToDrop -= (ssize_t)framesOut;
- if (activeTrack->mFramesToDrop <= 0) {
- activeTrack->clearSyncStartEvent();
- }
- } else {
- activeTrack->mFramesToDrop += framesOut;
- if (activeTrack->mFramesToDrop >= 0 || activeTrack->mSyncStartEvent == 0 ||
- activeTrack->mSyncStartEvent->isCancelled()) {
- ALOGW("Synced record %s, session %d, trigger session %d",
- (activeTrack->mFramesToDrop >= 0) ? "timed out" : "cancelled",
- activeTrack->sessionId(),
- (activeTrack->mSyncStartEvent != 0) ?
- activeTrack->mSyncStartEvent->triggerSession() :
- AUDIO_SESSION_NONE);
- activeTrack->clearSyncStartEvent();
- }
- }
}
-
if (framesOut == 0) {
break;
}
@@ -8575,20 +8546,10 @@
if (event == AudioSystem::SYNC_EVENT_NONE) {
recordTrack->clearSyncStartEvent();
} else if (event != AudioSystem::SYNC_EVENT_SAME) {
- recordTrack->mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
- triggerSession,
- recordTrack->sessionId(),
- syncStartEventCallback,
- recordTrack);
- // Sync event can be cancelled by the trigger session if the track is not in a
- // compatible state in which case we start record immediately
- if (recordTrack->mSyncStartEvent->isCancelled()) {
- recordTrack->clearSyncStartEvent();
- } else {
- // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs
- recordTrack->mFramesToDrop = -(ssize_t)
- ((AudioSystem::kSyncRecordStartTimeOutMs * recordTrack->mSampleRate) / 1000);
- }
+ recordTrack->mSynchronizedRecordState.startRecording(
+ mAudioFlinger->createSyncEvent(
+ event, triggerSession,
+ recordTrack->sessionId(), syncStartEventCallback, recordTrack));
}
{
@@ -8670,9 +8631,9 @@
}
}
-void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
+void AudioFlinger::RecordThread::syncStartEventCallback(const wp<audioflinger::SyncEvent>& event)
{
- sp<SyncEvent> strongEvent = event.promote();
+ sp<audioflinger::SyncEvent> strongEvent = event.promote();
if (strongEvent != 0) {
sp<RefBase> ptr = strongEvent->cookie().promote();
@@ -8711,12 +8672,14 @@
return false;
}
-bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event __unused) const
+bool AudioFlinger::RecordThread::isValidSyncEvent(
+ const sp<audioflinger::SyncEvent>& /* event */) const
{
return false;
}
-status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event __unused)
+status_t AudioFlinger::RecordThread::setSyncEvent(
+ const sp<audioflinger::SyncEvent>& event __unused)
{
#if 0 // This branch is currently dead code, but is preserved in case it will be needed in future
if (!isValidSyncEvent(event)) {
@@ -10249,12 +10212,13 @@
// and because it can cause a recursive mutex lock on stop().
}
-status_t AudioFlinger::MmapThread::setSyncEvent(const sp<SyncEvent>& event __unused)
+status_t AudioFlinger::MmapThread::setSyncEvent(const sp<audioflinger::SyncEvent>& /* event */)
{
return BAD_VALUE;
}
-bool AudioFlinger::MmapThread::isValidSyncEvent(const sp<SyncEvent>& event __unused) const
+bool AudioFlinger::MmapThread::isValidSyncEvent(
+ const sp<audioflinger::SyncEvent>& /* event */) const
{
return false;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 63ad4e6..45a4a95 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -516,8 +516,8 @@
audio_session_t sessionId,
bool threadLocked);
- virtual status_t setSyncEvent(const sp<SyncEvent>& event) = 0;
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+ virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
// Return a reference to a per-thread heap which can be used to allocate IMemory
// objects that will be read-only to client processes, read/write to mediaserver,
@@ -1002,8 +1002,8 @@
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::PlaybackThread::Track::Track().
- effect_buffer_t *sinkBuffer() const {
- return reinterpret_cast<effect_buffer_t *>(mSinkBuffer); };
+ float *sinkBuffer() const {
+ return reinterpret_cast<float *>(mSinkBuffer); };
virtual void detachAuxEffect_l(int effectId);
status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
@@ -1019,8 +1019,8 @@
virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId);
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
// called with AudioFlinger lock held
bool invalidateTracks_l(audio_stream_type_t streamType);
@@ -1581,6 +1581,8 @@
virtual void onAddNewTrack_l();
const audio_offload_info_t mOffloadInfo;
+
+ audioflinger::MonotonicFrameCounter mMonotonicFrameCounter; // for VolumeShaper
bool mVolumeShaperActive = false;
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
@@ -1919,10 +1921,10 @@
// FIXME replace by Set [and implement Bag/Multiset for other uses].
KeyedVector<audio_session_t, bool> sessionIds() const;
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
- static void syncStartEventCallback(const wp<SyncEvent>& event);
+ static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
virtual size_t frameCount() const { return mFrameCount; }
bool hasFastCapture() const { return mFastCapture != 0; }
@@ -2125,8 +2127,8 @@
// Note: using mActiveTracks as no mTracks here.
return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
}
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event);
+ virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const;
virtual void checkSilentMode_l() {}
virtual void processVolume_l() {}
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 42f7b47..6c42dc8 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -67,7 +67,7 @@
pid_t creatorPid,
uid_t uid,
bool isOut,
- alloc_type alloc = ALLOC_CBLK,
+ const alloc_type alloc = ALLOC_CBLK,
track_type type = TYPE_DEFAULT,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
std::string metricsId = {});
@@ -84,7 +84,7 @@
pid_t creatorPid() const { return mCreatorPid; }
audio_port_handle_t portId() const { return mPortId; }
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event);
sp<IMemory> getBuffers() const { return mBufferMemory; }
void* buffer() const { return mBuffer; }
@@ -350,6 +350,7 @@
// this could be a track type if needed later
const wp<ThreadBase> mThread;
+ const alloc_type mAllocType;
/*const*/ sp<Client> mClient; // see explanation at ~TrackBase() why not const
sp<IMemory> mCblkMemory;
audio_track_cblk_t* mCblk;
@@ -373,7 +374,7 @@
const audio_session_t mSessionId;
uid_t mUid;
- Vector < sp<SyncEvent> >mSyncEvents;
+ std::list<sp<audioflinger::SyncEvent>> mSyncEvents;
const bool mIsOut;
sp<ServerProxy> mServerProxy;
const int mId;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 123d5a9..5444c60 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -90,12 +90,13 @@
pid_t creatorPid,
uid_t clientUid,
bool isOut,
- alloc_type alloc,
+ const alloc_type alloc,
track_type type,
audio_port_handle_t portId,
std::string metricsId)
: RefBase(),
mThread(thread),
+ mAllocType(alloc),
mClient(client),
mCblk(NULL),
// mBuffer, mBufferSize
@@ -276,6 +277,10 @@
// relying on the automatic clear() at end of scope.
mClient.clear();
}
+ if (mAllocType == ALLOC_LOCAL) {
+ free(mBuffer);
+ mBuffer = nullptr;
+ }
// flush the binder command buffer
IPCThreadState::self()->flushCommands();
}
@@ -297,9 +302,10 @@
mServerProxy->releaseBuffer(&buf);
}
-status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(
+ const sp<audioflinger::SyncEvent>& event)
{
- mSyncEvents.add(event);
+ mSyncEvents.emplace_back(event);
return NO_ERROR;
}
@@ -1361,25 +1367,7 @@
const sp<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation)
{
- sp<VolumeShaper::Configuration> newConfiguration;
-
- if (isOffloadedOrDirect()) {
- const VolumeShaper::Configuration::OptionFlag optionFlag
- = configuration->getOptionFlags();
- if ((optionFlag & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) == 0) {
- ALOGW("%s(%d): %s tracks do not support frame counted VolumeShaper,"
- " using clock time instead",
- __func__, mId,
- isOffloaded() ? "Offload" : "Direct");
- newConfiguration = new VolumeShaper::Configuration(*configuration);
- newConfiguration->setOptionFlags(
- VolumeShaper::Configuration::OptionFlag(optionFlag
- | VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME));
- }
- }
-
- VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(
- (newConfiguration.get() != nullptr ? newConfiguration : configuration), operation);
+ VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
if (isOffloadedOrDirect()) {
// Signal thread to fetch new volume.
@@ -1625,12 +1613,13 @@
void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
{
- for (size_t i = 0; i < mSyncEvents.size();) {
- if (mSyncEvents[i]->type() == type) {
- mSyncEvents[i]->trigger();
- mSyncEvents.removeAt(i);
+ for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
+ if ((*it)->type() == type) {
+ ALOGV("%s: triggering SyncEvent type %d", __func__, type);
+ (*it)->trigger();
+ it = mSyncEvents.erase(it);
} else {
- ++i;
+ ++it;
}
}
}
@@ -1662,7 +1651,8 @@
return vlr;
}
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+ const sp<audioflinger::SyncEvent>& event)
{
if (isTerminated() || mState == PAUSED ||
((framesReady() == 0) && ((mSharedBuffer != 0) ||
@@ -1876,6 +1866,8 @@
}
}
+ ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
+ __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
mAudioTrackServerProxy->setDrained(drained);
// Set correction for flushed frames that are not accounted for in released.
local.mFlushed = mAudioTrackServerProxy->framesFlushed();
@@ -2410,7 +2402,6 @@
type, portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
mOverflow(false),
- mFramesToDrop(0),
mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
mRecordBufferConverter(NULL),
mFlags(flags),
@@ -2612,27 +2603,24 @@
result.append("\n");
}
-void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event)
+// This is invoked by SyncEvent callback.
+void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(
+ const sp<audioflinger::SyncEvent>& event)
{
- if (event == mSyncStartEvent) {
- ssize_t framesToDrop = 0;
- sp<ThreadBase> threadBase = mThread.promote();
- if (threadBase != 0) {
- // TODO: use actual buffer filling status instead of 2 buffers when info is available
- // from audio HAL
- framesToDrop = threadBase->mFrameCount * 2;
- }
- mFramesToDrop = framesToDrop;
+ size_t framesToDrop = 0;
+ sp<ThreadBase> threadBase = mThread.promote();
+ if (threadBase != 0) {
+ // TODO: use actual buffer filling status instead of 2 buffers when info is available
+ // from audio HAL
+ framesToDrop = threadBase->mFrameCount * 2;
}
+
+ mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
}
void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
{
- if (mSyncStartEvent != 0) {
- mSyncStartEvent->cancel();
- mSyncStartEvent.clear();
- }
- mFramesToDrop = 0;
+ mSynchronizedRecordState.clear();
}
void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
diff --git a/services/audioflinger/timing/Android.bp b/services/audioflinger/timing/Android.bp
new file mode 100644
index 0000000..269f796
--- /dev/null
+++ b/services/audioflinger/timing/Android.bp
@@ -0,0 +1,32 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_library {
+ name: "libaudioflinger_timing",
+
+ defaults: [
+ "audioflinger_flags_defaults",
+ ],
+
+ host_supported: true,
+
+ srcs: [
+ "MonotonicFrameCounter.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/services/audioflinger/timing/MonotonicFrameCounter.cpp b/services/audioflinger/timing/MonotonicFrameCounter.cpp
new file mode 100644
index 0000000..286f549
--- /dev/null
+++ b/services/audioflinger/timing/MonotonicFrameCounter.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "MonotonicFrameCounter"
+
+#include <utils/Log.h>
+#include "MonotonicFrameCounter.h"
+
+namespace android::audioflinger {
+
+int64_t MonotonicFrameCounter::updateAndGetMonotonicFrameCount(
+ int64_t newFrameCount, int64_t newTime) {
+ if (newFrameCount < 0 || newTime < 0) {
+ const auto result = getLastReportedFrameCount();
+ ALOGW("%s: invalid (frame, time) pair newFrameCount:%lld newFrameCount:%lld,"
+ " using %lld as frameCount",
+ __func__, (long long) newFrameCount, (long long)newFrameCount,
+ (long long)result);
+ return result;
+ }
+ if (newFrameCount < mLastReceivedFrameCount) {
+ const auto result = getLastReportedFrameCount();
+ ALOGW("%s: retrograde newFrameCount:%lld < mLastReceivedFrameCount:%lld,"
+ " ignoring, returning %lld as frameCount",
+ __func__, (long long) newFrameCount, (long long)mLastReceivedFrameCount,
+ (long long)result);
+ return result;
+ }
+ // Input looks fine.
+ // For better granularity, we could consider extrapolation on newTime.
+ mLastReceivedFrameCount = newFrameCount;
+ return getLastReportedFrameCount();
+}
+
+int64_t MonotonicFrameCounter::onFlush() {
+ ALOGV("%s: Updating mOffsetFrameCount:%lld with mLastReceivedFrameCount:%lld",
+ __func__, (long long)mOffsetFrameCount, (long long)mLastReceivedFrameCount);
+ mOffsetFrameCount += mLastReceivedFrameCount;
+ mLastReceivedFrameCount = 0;
+ return mOffsetFrameCount;
+}
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/MonotonicFrameCounter.h b/services/audioflinger/timing/MonotonicFrameCounter.h
new file mode 100644
index 0000000..0ea9510
--- /dev/null
+++ b/services/audioflinger/timing/MonotonicFrameCounter.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+namespace android::audioflinger {
+
+/**
+ * MonotonicFrameCounter
+ *
+ * Advances a monotonic frame count based on input timestamp pairs (frames, time).
+ * It takes into account a possible flush, which will "reset" the frames to 0.
+ *
+ * This class is used to drive VolumeShaper volume automation.
+ *
+ * The timestamps provided in updateAndGetMonotonicFrameCount should
+ * be of sufficient granularity for the purpose at hand. Currently no temporal
+ * extrapolation is done.
+ *
+ * This class is not thread safe.
+ */
+class MonotonicFrameCounter {
+public:
+ /**
+ * Receives a new timestamp pair (frames, time) and returns a monotonic frameCount.
+ *
+ * \param newFrameCount the frameCount currently played.
+ * \param newTime the time corresponding to the frameCount.
+ * \return a monotonic frame count usable for automation timing.
+ */
+ int64_t updateAndGetMonotonicFrameCount(int64_t newFrameCount, int64_t newTime);
+
+ /**
+ * Notifies when a flush occurs, whereupon the received frameCount sequence restarts at 0.
+ *
+ * \return the last reported frameCount.
+ */
+ int64_t onFlush();
+
+ /**
+ * Returns the received (input) frameCount to reported (output) frameCount offset.
+ *
+ * This offset is sufficient to ensure monotonicity after flush is called,
+ * suitability for any other purpose is *not* guaranteed.
+ */
+ int64_t getOffsetFrameCount() const { return mOffsetFrameCount; }
+
+ /**
+ * Returns the last received frameCount.
+ */
+ int64_t getLastReceivedFrameCount() const {
+ return mLastReceivedFrameCount;
+ }
+
+ /**
+ * Returns the last reported frameCount from updateAndGetMonotonicFrameCount().
+ */
+ int64_t getLastReportedFrameCount() const {
+ // This is consistent after onFlush().
+ return mOffsetFrameCount + mLastReceivedFrameCount;
+ }
+
+private:
+ int64_t mOffsetFrameCount = 0;
+ int64_t mLastReceivedFrameCount = 0;
+};
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/SyncEvent.h b/services/audioflinger/timing/SyncEvent.h
new file mode 100644
index 0000000..b5a3b40
--- /dev/null
+++ b/services/audioflinger/timing/SyncEvent.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+
+#include <media/AudioSystem.h>
+#include <utils/RefBase.h>
+
+namespace android::audioflinger {
+
+class SyncEvent;
+using SyncEventCallback = std::function<void(const wp<SyncEvent>& event)>;
+
+class SyncEvent : public RefBase {
+public:
+ SyncEvent(AudioSystem::sync_event_t type,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
+ const SyncEventCallback& callBack,
+ const wp<RefBase>& cookie)
+ : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
+ mCookie(cookie), mCallback(callBack)
+ {}
+
+ void trigger() {
+ std::lock_guard l(mLock);
+ if (mCallback) mCallback(wp<SyncEvent>::fromExisting(this));
+ }
+
+ bool isCancelled() const {
+ std::lock_guard l(mLock);
+ return mCallback == nullptr;
+ }
+
+ void cancel() {
+ std::lock_guard l(mLock);
+ mCallback = nullptr;
+ }
+
+ AudioSystem::sync_event_t type() const { return mType; }
+ audio_session_t triggerSession() const { return mTriggerSession; }
+ audio_session_t listenerSession() const { return mListenerSession; }
+ const wp<RefBase>& cookie() const { return mCookie; }
+
+private:
+ const AudioSystem::sync_event_t mType;
+ const audio_session_t mTriggerSession;
+ const audio_session_t mListenerSession;
+ const wp<RefBase> mCookie;
+ mutable std::mutex mLock;
+ SyncEventCallback mCallback GUARDED_BY(mLock);
+};
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/SynchronizedRecordState.h b/services/audioflinger/timing/SynchronizedRecordState.h
new file mode 100644
index 0000000..f40d41b
--- /dev/null
+++ b/services/audioflinger/timing/SynchronizedRecordState.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "SyncEvent.h"
+
+#pragma push_macro("LOG_TAG")
+#undef LOG_TAG
+#define LOG_TAG "SynchronizedRecordState"
+
+namespace android::audioflinger {
+
+class SynchronizedRecordState {
+public:
+ explicit SynchronizedRecordState(uint32_t sampleRate)
+ : mSampleRate(sampleRate)
+ {}
+
+ void clear() {
+ std::lock_guard lg(mLock);
+ clear_l();
+ }
+
+ // Called by the RecordThread when recording is starting.
+ void startRecording(const sp<SyncEvent>& event) {
+ std::lock_guard lg(mLock);
+ mSyncStartEvent = event;
+ // Sync event can be cancelled by the trigger session if the track is not in a
+ // compatible state in which case we start record immediately
+ if (mSyncStartEvent->isCancelled()) {
+ clear_l();
+ } else {
+ mFramesToDrop = -(ssize_t)
+ ((AudioSystem::kSyncRecordStartTimeOutMs * mSampleRate) / 1000);
+ }
+ }
+
+ // Invoked by SyncEvent callback.
+ void onPlaybackFinished(const sp<SyncEvent>& event, size_t framesToDrop = 1) {
+ std::lock_guard lg(mLock);
+ if (event == mSyncStartEvent) {
+ mFramesToDrop = framesToDrop; // compute this
+ ALOGV("%s: framesToDrop:%zd", __func__, mFramesToDrop);
+ }
+ }
+
+ // Returns the current FramesToDrop counter
+ //
+ // if <0 waiting (drop the frames)
+ // if >0 draining (drop the frames)
+ // else if ==0 proceed to record.
+ ssize_t updateRecordFrames(size_t frames) {
+ std::lock_guard lg(mLock);
+ if (mFramesToDrop > 0) {
+ // we've been triggered, we count down for start delay
+ ALOGV("%s: trigger countdown %zd by %zu frames", __func__, mFramesToDrop, frames);
+ mFramesToDrop -= (ssize_t)frames;
+ if (mFramesToDrop <= 0) clear_l();
+ } else if (mFramesToDrop < 0) {
+ // we're waiting to be triggered.
+ // ALOGD("%s: timeout countup %zd with %zu frames", __func__, mFramesToDrop, frames);
+ mFramesToDrop += (ssize_t)frames;
+ if (mFramesToDrop >= 0 || !mSyncStartEvent || mSyncStartEvent->isCancelled()) {
+ ALOGW("Synced record %s, trigger session %d",
+ (mFramesToDrop >= 0) ? "timed out" : "cancelled",
+ (mSyncStartEvent) ? mSyncStartEvent->triggerSession()
+ : AUDIO_SESSION_NONE);
+ clear_l();
+ }
+ }
+ return mFramesToDrop;
+ }
+
+private:
+ const uint32_t mSampleRate;
+
+ std::mutex mLock;
+ // number of captured frames to drop after the start sync event has been received.
+ // when < 0, maximum frames to drop before starting capture even if sync event is
+ // not received
+ ssize_t mFramesToDrop GUARDED_BY(mLock) = 0;
+
+ // sync event triggering actual audio capture. Frames read before this event will
+ // be dropped and therefore not read by the application.
+ sp<SyncEvent> mSyncStartEvent GUARDED_BY(mLock);
+
+ void clear_l() REQUIRES(mLock) {
+ if (mSyncStartEvent) {
+ mSyncStartEvent->cancel();
+ mSyncStartEvent.clear();
+ }
+ mFramesToDrop = 0;
+ }
+};
+
+} // namespace android::audioflinger
+
+#pragma pop_macro("LOG_TAG")
diff --git a/services/audioflinger/timing/tests/Android.bp b/services/audioflinger/timing/tests/Android.bp
new file mode 100644
index 0000000..d1e5563
--- /dev/null
+++ b/services/audioflinger/timing/tests/Android.bp
@@ -0,0 +1,79 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_test {
+ name: "mediasyncevent_tests",
+
+ host_supported: true,
+
+ srcs: [
+ "mediasyncevent_tests.cpp"
+ ],
+
+ header_libs: [
+ "libaudioclient_headers",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libutils", // RefBase
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+cc_test {
+ name: "monotonicframecounter_tests",
+
+ host_supported: true,
+
+ srcs: [
+ "monotonicframecounter_tests.cpp"
+ ],
+
+ static_libs: [
+ "libaudioflinger_timing",
+ "liblog",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+cc_test {
+ name: "synchronizedrecordstate_tests",
+
+ host_supported: true,
+
+ srcs: [
+ "synchronizedrecordstate_tests.cpp"
+ ],
+
+ header_libs: [
+ "libaudioclient_headers",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libutils", // RefBase
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ }
\ No newline at end of file
diff --git a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
new file mode 100644
index 0000000..2922d90
--- /dev/null
+++ b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "mediasyncevent_tests"
+
+#include "../SyncEvent.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(MediaSyncEventTests, Basic) {
+ struct Cookie : public RefBase {};
+
+ // These variables are set by trigger().
+ bool triggered = false;
+ wp<SyncEvent> param;
+
+ constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+ constexpr auto triggerSession = audio_session_t(10);
+ constexpr auto listenerSession = audio_session_t(11);
+ const SyncEventCallback callback =
+ [&](const wp<SyncEvent>& event) {
+ triggered = true;
+ param = event;
+ };
+ const auto cookie = sp<Cookie>::make();
+
+ // Since the callback uses a weak pointer to this,
+ // don't allocate on the stack.
+ auto syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+
+ ASSERT_EQ(type, syncEvent->type());
+ ASSERT_EQ(triggerSession, syncEvent->triggerSession());
+ ASSERT_EQ(listenerSession, syncEvent->listenerSession());
+ ASSERT_EQ(cookie, syncEvent->cookie());
+ ASSERT_FALSE(triggered);
+
+ syncEvent->trigger();
+ ASSERT_TRUE(triggered);
+ ASSERT_EQ(param, syncEvent);
+
+ ASSERT_FALSE(syncEvent->isCancelled());
+ syncEvent->cancel();
+ ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+} // namespace
diff --git a/services/audioflinger/timing/tests/monotonicframecounter_tests.cpp b/services/audioflinger/timing/tests/monotonicframecounter_tests.cpp
new file mode 100644
index 0000000..7aaa4fa
--- /dev/null
+++ b/services/audioflinger/timing/tests/monotonicframecounter_tests.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "monotonicframecounter_tests"
+
+#include "../MonotonicFrameCounter.h"
+
+#include <gtest/gtest.h>
+
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(MonotonicFrameCounterTest, SimpleProgression) {
+ MonotonicFrameCounter monotonicFrameCounter;
+
+ const std::vector<std::pair<int64_t, int64_t>> frametimes{
+ {0, 0}, {100, 100}, {200, 200},
+ };
+
+ int64_t maxReceivedFrameCount = 0;
+ for (const auto& p : frametimes) {
+ maxReceivedFrameCount = std::max(maxReceivedFrameCount, p.first);
+ ASSERT_EQ(p.first,
+ monotonicFrameCounter.updateAndGetMonotonicFrameCount(p.first, p.second));
+ }
+ ASSERT_EQ(maxReceivedFrameCount, monotonicFrameCounter.getLastReportedFrameCount());
+}
+
+TEST(MonotonicFrameCounterTest, InvalidData) {
+ MonotonicFrameCounter monotonicFrameCounter;
+
+ const std::vector<std::pair<int64_t, int64_t>> frametimes{
+ {-1, -1}, {100, 100}, {-1, -1}, {90, 90}, {200, 200},
+ };
+
+ int64_t prevFrameCount = 0;
+ int64_t maxReceivedFrameCount = 0;
+ for (const auto& p : frametimes) {
+ maxReceivedFrameCount = std::max(maxReceivedFrameCount, p.first);
+ const int64_t frameCount =
+ monotonicFrameCounter.updateAndGetMonotonicFrameCount(p.first, p.second);
+ // we must be monotonic
+ ASSERT_GE(frameCount, prevFrameCount);
+ prevFrameCount = frameCount;
+ }
+ ASSERT_EQ(maxReceivedFrameCount, monotonicFrameCounter.getLastReportedFrameCount());
+}
+
+TEST(MonotonicFrameCounterTest, Flush) {
+ MonotonicFrameCounter monotonicFrameCounter;
+
+ // Different playback sequences are separated by a flush.
+ const std::vector<std::vector<std::pair<int64_t, int64_t>>> frameset{
+ {{-1, -1}, {100, 10}, {200, 20}, {300, 30},},
+ {{-1, -1}, {100, 10}, {200, 20}, {300, 30},},
+ {{-1, -1}, {100, 100}, {-1, -1}, {90, 90}, {200, 200},},
+ };
+
+ int64_t prevFrameCount = 0;
+ int64_t maxReceivedFrameCount = 0;
+ int64_t sumMaxReceivedFrameCount = 0;
+ for (const auto& v : frameset) {
+ for (const auto& p : v) {
+ maxReceivedFrameCount = std::max(maxReceivedFrameCount, p.first);
+ const int64_t frameCount =
+ monotonicFrameCounter.updateAndGetMonotonicFrameCount(p.first, p.second);
+ // we must be monotonic
+ ASSERT_GE(frameCount, prevFrameCount);
+ prevFrameCount = frameCount;
+ }
+ monotonicFrameCounter.onFlush();
+ sumMaxReceivedFrameCount += maxReceivedFrameCount;
+ maxReceivedFrameCount = 0;
+ }
+
+ // On flush we keep a monotonic reported framecount
+ // even though the received framecount resets to 0.
+ // The requirement of equality here is implementation dependent.
+ ASSERT_EQ(sumMaxReceivedFrameCount, monotonicFrameCounter.getLastReportedFrameCount());
+}
+
+} // namespace
diff --git a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
new file mode 100644
index 0000000..ee5d269
--- /dev/null
+++ b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "synchronizedrecordstate_tests"
+
+#include "../SynchronizedRecordState.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(SynchronizedRecordStateTests, Basic) {
+ struct Cookie : public RefBase {};
+
+ // These variables are set by trigger().
+ bool triggered = false;
+ wp<SyncEvent> param;
+
+ constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+ constexpr auto triggerSession = audio_session_t(10);
+ constexpr auto listenerSession = audio_session_t(11);
+ const SyncEventCallback callback =
+ [&](const wp<SyncEvent>& event) {
+ triggered = true;
+ param = event;
+ };
+ const auto cookie = sp<Cookie>::make();
+
+ // Check timeout.
+ SynchronizedRecordState recordState(48000 /* sampleRate */);
+ auto syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+ recordState.startRecording(syncEvent);
+ recordState.updateRecordFrames(2);
+ ASSERT_FALSE(triggered);
+ ASSERT_EQ(0, recordState.updateRecordFrames(1'000'000'000));
+ ASSERT_FALSE(triggered);
+ ASSERT_TRUE(syncEvent->isCancelled());
+
+ // Check count down after track is complete.
+ syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+ recordState.startRecording(syncEvent);
+ recordState.onPlaybackFinished(syncEvent, 10);
+ ASSERT_EQ(1, recordState.updateRecordFrames(9));
+ ASSERT_FALSE(triggered);
+ ASSERT_EQ(0, recordState.updateRecordFrames(2));
+ ASSERT_FALSE(triggered);
+ ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 0a9e6eb..e170713 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -310,13 +310,13 @@
virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
virtual status_t getProductStrategyFromAudioAttributes(
- const AudioAttributes &aa, product_strategy_t &productStrategy,
+ const audio_attributes_t &aa, product_strategy_t &productStrategy,
bool fallbackOnDefault) = 0;
virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
virtual status_t getVolumeGroupFromAudioAttributes(
- const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault) = 0;
+ const audio_attributes_t &aa, volume_group_t &volumeGroup, bool fallbackOnDefault) = 0;
virtual bool isCallScreenModeSupported() = 0;
@@ -418,6 +418,8 @@
public:
virtual ~AudioPolicyClientInterface() {}
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig *config) = 0;
+
//
// Audio HW module functions
//
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 3df23f1..972de02 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -7,9 +7,13 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_library_static {
+cc_library {
name: "libaudiopolicycomponents",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"src/AudioCollections.cpp",
"src/AudioInputDescriptor.cpp",
@@ -30,7 +34,11 @@
"src/TypeConverter.cpp",
],
shared_libs: [
+ "audioclient-types-aidl-cpp",
+ "audiopolicy-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudiofoundation",
+ "libaudiopolicy",
"libbase",
"libcutils",
"libhidlbase",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index b24fce8..1f6002f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -23,6 +23,7 @@
#include <DeviceDescriptor.h>
#include <HwModule.h>
+#include <android/media/AudioPolicyConfig.h>
#include <error/Result.h>
#include <utils/StrongPointer.h>
#include <utils/RefBase.h>
@@ -42,11 +43,18 @@
// Surround formats, with an optional list of subformats that are equivalent from users' POV.
using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
+ // The source used to indicate the configuration from the AIDL HAL.
+ static const constexpr char* const kAidlConfigSource = "AIDL HAL";
// The source used to indicate the default fallback configuration.
static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
+ // The suffix of the "engine default" implementation shared library name.
+ static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
// Creates the default (fallback) configuration.
static sp<const AudioPolicyConfig> createDefault();
+ // Attempts to load the configuration from the AIDL config falls back to default on failure.
+ static sp<const AudioPolicyConfig> loadFromApmAidlConfigWithFallback(
+ const media::AudioPolicyConfig& aidl);
// Attempts to load the configuration from the XML file, falls back to default on failure.
// If the XML file path is not provided, uses `audio_get_audio_policy_config_file` function.
static sp<const AudioPolicyConfig> loadFromApmXmlConfigWithFallback(
@@ -114,12 +122,6 @@
mDefaultOutputDevice = defaultDevice;
}
- bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
- void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
- {
- mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
- }
-
bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
void setCallScreenModeSupported(bool isCallScreenModeSupported)
{
@@ -135,33 +137,24 @@
{
mSurroundFormats = surroundFormats;
}
- void setSurroundFormats(SurroundFormats &&surroundFormats)
- {
- mSurroundFormats = std::move(surroundFormats);
- }
void setDefault();
private:
friend class sp<AudioPolicyConfig>;
- static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
-
AudioPolicyConfig() = default;
void augmentData();
+ status_t loadFromAidl(const media::AudioPolicyConfig& aidl);
status_t loadFromXml(const std::string& xmlFilePath, bool forVts);
std::string mSource; // Not kDefaultConfigSource. Empty source means an empty config.
std::string mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
HwModuleCollection mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
- DeviceVector mOutputDevices;
- DeviceVector mInputDevices;
+ DeviceVector mOutputDevices; // Attached output devices.
+ DeviceVector mInputDevices; // Attached input devices.
sp<DeviceDescriptor> mDefaultOutputDevice;
- // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
- // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
- // Note: remove also speaker_drc_enabled from global configuration of XML config file.
- bool mIsSpeakerDrcEnabled = false;
bool mIsCallScreenModeSupported = false;
SurroundFormats mSurroundFormats;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 436fcc1..e994758 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -39,7 +39,8 @@
class HwModule : public RefBase
{
public:
- explicit HwModule(const char *name, uint32_t halVersionMajor = 0, uint32_t halVersionMinor = 0);
+ explicit HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor);
+ HwModule(const char *name, uint32_t halVersion = 0);
~HwModule();
const char *getName() const { return mName.string(); }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 575a6c5..e214ae9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -19,6 +19,9 @@
#include <AudioPolicyConfig.h>
#include <IOProfile.h>
#include <Serializer.h>
+#include <hardware/audio.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
#include <media/AudioProfile.h>
#include <system/audio.h>
#include <system/audio_config.h>
@@ -26,6 +29,142 @@
namespace android {
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+
+namespace {
+
+ConversionResult<sp<PolicyAudioPort>>
+aidl2legacy_portId_PolicyAudioPort(int32_t portId,
+ const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+ if (auto it = ports.find(portId); it != ports.end()) {
+ return it->second;
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<sp<AudioRoute>>
+aidl2legacy_AudioRoute(const media::AudioRoute& aidl,
+ const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+ auto legacy = sp<AudioRoute>::make(aidl.isExclusive ? AUDIO_ROUTE_MUX : AUDIO_ROUTE_MIX);
+ auto legacySink = VALUE_OR_RETURN(aidl2legacy_portId_PolicyAudioPort(aidl.sinkPortId, ports));
+ legacy->setSink(legacySink);
+ PolicyAudioPortVector legacySources;
+ for (int32_t portId : aidl.sourcePortIds) {
+ sp<PolicyAudioPort> legacyPort = VALUE_OR_RETURN(
+ aidl2legacy_portId_PolicyAudioPort(portId, ports));
+ legacySources.add(legacyPort);
+ }
+ legacy->setSources(legacySources);
+ legacySink->addRoute(legacy);
+ for (const auto& legacySource : legacySources) {
+ legacySource->addRoute(legacy);
+ }
+ return legacy;
+}
+
+status_t aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule& aidl,
+ sp<HwModule>* legacy,
+ DeviceVector* attachedInputDevices, DeviceVector* attachedOutputDevices,
+ sp<DeviceDescriptor>* defaultOutputDevice) {
+ *legacy = sp<HwModule>::make(aidl.name.c_str(), AUDIO_DEVICE_API_VERSION_CURRENT);
+ audio_module_handle_t legacyHandle = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_int32_t_audio_module_handle_t(aidl.handle));
+ (*legacy)->setHandle(legacyHandle);
+ IOProfileCollection mixPorts;
+ DeviceVector devicePorts;
+ const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+ std::unordered_map<int32_t, sp<PolicyAudioPort>> ports;
+ for (const auto& aidlPort : aidl.ports) {
+ const bool isInput = aidlPort.flags.getTag() == AudioIoFlags::input;
+ audio_port_v7 legacyPort = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPort_audio_port_v7(aidlPort, isInput));
+ // This conversion fills out both 'hal' and 'sys' parts.
+ media::AudioPortFw fwPort = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_v7_AudioPortFw(legacyPort));
+ // Since audio_port_v7 lacks some fields, for example, 'maxOpen/ActiveCount',
+ // replace the converted data with the actual data from the HAL.
+ fwPort.hal = aidlPort;
+ if (aidlPort.ext.getTag() == AudioPortExt::mix) {
+ auto mixPort = sp<IOProfile>::make("", AUDIO_PORT_ROLE_NONE);
+ RETURN_STATUS_IF_ERROR(mixPort->readFromParcelable(fwPort));
+ sortAudioProfiles(mixPort->getAudioProfiles());
+ mixPorts.add(mixPort);
+ ports.emplace(aidlPort.id, mixPort);
+ } else if (aidlPort.ext.getTag() == AudioPortExt::device) {
+ // In the legacy XML, device ports use 'tagName' instead of 'AudioPort.name'.
+ auto devicePort =
+ sp<DeviceDescriptor>::make(AUDIO_DEVICE_NONE, aidlPort.name);
+ RETURN_STATUS_IF_ERROR(devicePort->readFromParcelable(fwPort));
+ devicePort->setName("");
+ auto& profiles = devicePort->getAudioProfiles();
+ if (profiles.empty()) {
+ profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
+ } else {
+ sortAudioProfiles(profiles);
+ }
+ devicePorts.add(devicePort);
+ ports.emplace(aidlPort.id, devicePort);
+
+ if (const auto& deviceExt = aidlPort.ext.get<AudioPortExt::device>();
+ deviceExt.device.type.connection.empty()) { // Attached device
+ if (isInput) {
+ attachedInputDevices->add(devicePort);
+ } else {
+ attachedOutputDevices->add(devicePort);
+ if ((deviceExt.flags & defaultDeviceFlag) != 0) {
+ *defaultOutputDevice = devicePort;
+ }
+ }
+ }
+ } else {
+ return BAD_VALUE;
+ }
+ }
+ (*legacy)->setProfiles(mixPorts);
+ (*legacy)->setDeclaredDevices(devicePorts);
+ AudioRouteVector routes;
+ for (const auto& aidlRoute : aidl.routes) {
+ sp<AudioRoute> legacy = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioRoute(aidlRoute, ports));
+ routes.add(legacy);
+ }
+ (*legacy)->setRoutes(routes);
+ return OK;
+}
+
+status_t aidl2legacy_AudioHwModules_HwModuleCollection(
+ const std::vector<media::AudioHwModule>& aidl,
+ HwModuleCollection* legacyModules, DeviceVector* attachedInputDevices,
+ DeviceVector* attachedOutputDevices, sp<DeviceDescriptor>* defaultOutputDevice) {
+ for (const auto& aidlModule : aidl) {
+ sp<HwModule> legacy;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModule_HwModule(aidlModule, &legacy,
+ attachedInputDevices, attachedOutputDevices, defaultOutputDevice));
+ legacyModules->add(legacy);
+ }
+ return OK;
+}
+
+using SurroundFormatFamily = AudioPolicyConfig::SurroundFormats::value_type;
+ConversionResult<SurroundFormatFamily>
+aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily& aidl) {
+ audio_format_t legacyPrimary = VALUE_OR_RETURN(
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.primaryFormat));
+ std::unordered_set<audio_format_t> legacySubs = VALUE_OR_RETURN(
+ convertContainer<std::unordered_set<audio_format_t>>(
+ aidl.subFormats, aidl2legacy_AudioFormatDescription_audio_format_t));
+ return std::make_pair(legacyPrimary, legacySubs);
+}
+
+ConversionResult<AudioPolicyConfig::SurroundFormats>
+aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig& aidl) {
+ return convertContainer<AudioPolicyConfig::SurroundFormats>(aidl.formatFamilies,
+ aidl2legacy_SurroundFormatFamily);
+};
+
+} // namespace
+
// static
sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
auto config = sp<AudioPolicyConfig>::make();
@@ -34,6 +173,16 @@
}
// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmAidlConfigWithFallback(
+ const media::AudioPolicyConfig& aidl) {
+ auto config = sp<AudioPolicyConfig>::make();
+ if (status_t status = config->loadFromAidl(aidl); status == NO_ERROR) {
+ return config;
+ }
+ return createDefault();
+}
+
+// static
sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
const std::string& xmlFilePath) {
const std::string filePath =
@@ -41,9 +190,8 @@
auto config = sp<AudioPolicyConfig>::make();
if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) {
return config;
- } else {
- return createDefault();
}
+ return createDefault();
}
// static
@@ -101,6 +249,18 @@
}
}
+status_t AudioPolicyConfig::loadFromAidl(const media::AudioPolicyConfig& aidl) {
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModules_HwModuleCollection(aidl.modules,
+ &mHwModules, &mInputDevices, &mOutputDevices, &mDefaultOutputDevice));
+ mIsCallScreenModeSupported = std::find(aidl.supportedModes.begin(), aidl.supportedModes.end(),
+ media::audio::common::AudioMode::CALL_SCREEN) != aidl.supportedModes.end();
+ mSurroundFormats = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
+ mSource = kAidlConfigSource;
+ // No need to augmentData() as AIDL HAL must provide correct mic addresses.
+ return NO_ERROR;
+}
+
status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
if (xmlFilePath.empty()) {
ALOGE("Audio policy configuration file name is empty");
@@ -132,7 +292,8 @@
mOutputDevices.add(mDefaultOutputDevice);
mInputDevices.add(defaultInputDevice);
- sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
+ sp<HwModule> module = new HwModule(
+ AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_DEVICE_API_VERSION_2_0);
mHwModules.add(module);
sp<OutputProfile> outProfile = new OutputProfile("primary");
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 418b7eb..5f14ee4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -33,6 +33,13 @@
setHalVersion(halVersionMajor, halVersionMinor);
}
+HwModule::HwModule(const char *name, uint32_t halVersion)
+ : mName(String8(name)),
+ mHandle(AUDIO_MODULE_HANDLE_NONE),
+ mHalVersion(halVersion)
+{
+}
+
HwModule::~HwModule()
{
for (size_t i = 0; i < mOutputProfiles.size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 21f2018..2cbdeaa 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -68,7 +68,7 @@
if (checkExactAudioProfile(&config) != NO_ERROR) {
return false;
}
- } else if (checkCompatibleAudioProfile(
+ } else if (checkExactAudioProfile(&config) != NO_ERROR && checkCompatibleAudioProfile(
myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) {
return false;
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 1b48dc3..3d5c1d2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -197,7 +197,6 @@
struct Attributes
{
- static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
static constexpr const char *engineLibrarySuffix = "engine_library";
};
@@ -770,12 +769,7 @@
for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(GlobalConfigTraits::tag))) {
bool value;
- std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
- if (!attr.empty() &&
- convertTo<std::string, bool>(attr, value)) {
- config->setSpeakerDrcEnabled(value);
- }
- attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
+ std::string attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
if (!attr.empty() &&
convertTo<std::string, bool>(attr, value)) {
config->setCallScreenModeSupported(value);
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index 50c5eab..6c46c54 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -51,10 +51,10 @@
"libaudiopolicyengine_common_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_config",
],
shared_libs: [
"libaudiofoundation",
+ "libaudiopolicycomponents",
],
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index abacd3c..5f4080e 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -16,6 +16,9 @@
#pragma once
+#include <functional>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <EngineConfig.h>
#include <EngineInterface.h>
#include <ProductStrategy.h>
@@ -110,6 +113,9 @@
status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
AudioDeviceTypeAddrVector &devices) const override;
+ engineConfig::ParsingResult loadAudioPolicyEngineConfig(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig);
+
engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
@@ -167,6 +173,8 @@
void updateDeviceSelectionCache() override;
private:
+ engineConfig::ParsingResult processParsingResult(engineConfig::ParsingResult&& rawResult);
+
/**
* Get media devices as the given role
*
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 2aa2f9a..1593be0 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -24,7 +24,7 @@
#include <vector>
#include <HandleGenerator.h>
-#include <media/AudioAttributes.h>
+#include <media/VolumeGroupAttributes.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioPolicy.h>
@@ -43,25 +43,20 @@
class ProductStrategy : public virtual RefBase, private HandleGenerator<uint32_t>
{
private:
- struct AudioAttributes {
- audio_stream_type_t mStream = AUDIO_STREAM_DEFAULT;
- volume_group_t mVolumeGroup = VOLUME_GROUP_NONE;
- audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
- };
-
- using AudioAttributesVector = std::vector<AudioAttributes>;
+ using VolumeGroupAttributesVector = std::vector<VolumeGroupAttributes>;
public:
ProductStrategy(const std::string &name);
- void addAttributes(const AudioAttributes &audioAttributes);
+ void addAttributes(const VolumeGroupAttributes &volumeGroupAttributes);
- std::vector<android::AudioAttributes> listAudioAttributes() const;
+ std::vector<android::VolumeGroupAttributes> listVolumeGroupAttributes() const;
std::string getName() const { return mName; }
AttributesVector getAudioAttributes() const;
product_strategy_t getId() const { return mId; }
StreamTypeVector getSupportedStreams() const;
+ VolumeGroupAttributesVector getVolumeGroupAttributes() const { return mAttributesVector; }
/**
* @brief matches checks if the given audio attributes shall follow the strategy.
@@ -69,9 +64,9 @@
* If only the usage is available, the check is performed on the usages of the given
* attributes, otherwise all fields must match.
* @param attributes to consider
- * @return true if attributes matches with the strategy, false otherwise.
+ * @return matching score, negative value if no match.
*/
- bool matches(const audio_attributes_t attributes) const;
+ int matchesScore(const audio_attributes_t attributes) const;
bool supportStreamType(const audio_stream_type_t &streamType) const;
@@ -90,9 +85,6 @@
DeviceTypeSet getDeviceTypes() const { return mApplicableDevices; }
audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
- audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
-
- volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
@@ -105,7 +97,7 @@
private:
std::string mName;
- AudioAttributesVector mAttributesVector;
+ VolumeGroupAttributesVector mAttributesVector;
product_strategy_t mId;
@@ -167,6 +159,9 @@
void dump(String8 *dst, int spaces = 0) const;
private:
+ VolumeGroupAttributes getVolumeGroupAttributesForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault = true) const;
+
product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
};
diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h
index 5378f64..f40ab1c 100644
--- a/services/audiopolicy/engine/common/include/VolumeGroup.h
+++ b/services/audiopolicy/engine/common/include/VolumeGroup.h
@@ -39,7 +39,7 @@
VolumeCurves *getVolumeCurves() { return &mGroupVolumeCurves; }
void addSupportedAttributes(const audio_attributes_t &attr);
- AttributesVector getSupportedAttributes() const { return mGroupVolumeCurves.getAttributes(); }
+ AttributesVector getSupportedAttributes() const;
void addSupportedStream(audio_stream_type_t stream);
StreamTypeVector getStreamTypes() const { return mGroupVolumeCurves.getStreamTypes(); }
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index fe5cd9f..adb1ca3 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -115,10 +115,53 @@
return PRODUCT_STRATEGY_NONE;
}
+engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig)
+{
+ engineConfig::ParsingResult result = engineConfig::convert(aidlConfig);
+ if (result.parsedConfig == nullptr) {
+ ALOGE("%s: There was an error parsing AIDL data", __func__);
+ result = {std::make_unique<engineConfig::Config>(gDefaultEngineConfig), 1};
+ } else {
+ // It is allowed for the HAL to return an empty list of strategies.
+ if (result.parsedConfig->productStrategies.empty()) {
+ result.parsedConfig->productStrategies = gDefaultEngineConfig.productStrategies;
+ }
+ }
+ return processParsingResult(std::move(result));
+}
+
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
{
+ auto fileExists = [](const char* path) {
+ struct stat fileStat;
+ return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
+ };
+ const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
+ engineConfig::ParsingResult result =
+ fileExists(filePath.c_str()) ?
+ engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
+ if (result.parsedConfig == nullptr) {
+ ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
+ engineConfig::Config config = gDefaultEngineConfig;
+ android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
+ result = {std::make_unique<engineConfig::Config>(config),
+ static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
+ } else {
+ // Append for internal use only volume groups (e.g. rerouting/patch)
+ result.parsedConfig->volumeGroups.insert(
+ std::end(result.parsedConfig->volumeGroups),
+ std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
+ }
+ ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+ return processParsingResult(std::move(result));
+}
+
+engineConfig::ParsingResult EngineBase::processParsingResult(
+ engineConfig::ParsingResult&& rawResult)
+{
auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
- // Ensure name unicity to prevent duplicate
+ // Ensure volume group name uniqueness.
LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),
[&volumeConfig](const auto &volumeGroup) {
return volumeConfig.name == volumeGroup.second->getName(); }),
@@ -145,7 +188,7 @@
};
auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
for (const auto &attr : group.attributesVect) {
- strategy->addAttributes({group.stream, volumeGroup->getId(), attr});
+ strategy->addAttributes({volumeGroup->getId(), group.stream, attr});
volumeGroup->addSupportedAttributes(attr);
}
};
@@ -158,42 +201,21 @@
});
return iter != end(volumeGroups);
};
- auto fileExists = [](const char* path) {
- struct stat fileStat;
- return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
- };
- const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
- auto result = fileExists(filePath.c_str()) ?
- engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
- if (result.parsedConfig == nullptr) {
- ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
- engineConfig::Config config = gDefaultEngineConfig;
- android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
- result = {std::make_unique<engineConfig::Config>(config),
- static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
- } else {
- // Append for internal use only volume groups (e.g. rerouting/patch)
- result.parsedConfig->volumeGroups.insert(
- std::end(result.parsedConfig->volumeGroups),
- std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
- }
+ auto result = std::move(rawResult);
// Append for internal use only strategies (e.g. rerouting/patch)
result.parsedConfig->productStrategies.insert(
std::end(result.parsedConfig->productStrategies),
std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
-
- ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
-
engineConfig::VolumeGroup defaultVolumeConfig;
engineConfig::VolumeGroup defaultSystemVolumeConfig;
for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
// save default volume config for streams not defined in configuration
- if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
+ if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_MUSIC)) == 0) {
defaultVolumeConfig = volumeConfig;
}
- if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
+ if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_PATCH)) == 0) {
defaultSystemVolumeConfig = volumeConfig;
}
loadVolumeConfig(mVolumeGroups, volumeConfig);
@@ -285,7 +307,7 @@
for (const auto &iter : mProductStrategies) {
const auto &productStrategy = iter.second;
strategies.push_back(
- {productStrategy->getName(), productStrategy->listAudioAttributes(),
+ {productStrategy->getName(), productStrategy->listVolumeGroupAttributes(),
productStrategy->getId()});
}
return NO_ERROR;
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index b036e12..f132ced 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -16,6 +16,8 @@
#pragma once
+#include <EngineConfig.h>
+
#include <system/audio.h>
namespace android {
@@ -25,11 +27,11 @@
const engineConfig::ProductStrategies gOrderedStrategies = {
{"STRATEGY_PHONE",
{
- {"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
+ {AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""}},
},
- {"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
+ {AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
""}},
}
@@ -37,11 +39,11 @@
},
{"STRATEGY_SONIFICATION",
{
- {"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
+ {AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
},
- {"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
+ {AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""}},
}
@@ -49,7 +51,7 @@
},
{"STRATEGY_ENFORCED_AUDIBLE",
{
- {"", AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
+ {AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_AUDIBILITY_ENFORCED, ""}}
}
@@ -57,7 +59,7 @@
},
{"STRATEGY_ACCESSIBILITY",
{
- {"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
+ {AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
}
@@ -65,7 +67,7 @@
},
{"STRATEGY_SONIFICATION_RESPECTFUL",
{
- {"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
+ {AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""},
@@ -77,11 +79,11 @@
},
{"STRATEGY_MEDIA",
{
- {"assistant", AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
+ {AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
{{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
},
- {"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
+ {AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""},
@@ -95,7 +97,7 @@
AUDIO_FLAG_NONE, ""}
},
},
- {"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
+ {AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
}
@@ -103,7 +105,7 @@
},
{"STRATEGY_DTMF",
{
- {"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
+ {AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
@@ -113,7 +115,7 @@
},
{"STRATEGY_CALL_ASSISTANT",
{
- {"", AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
+ {AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_NONE, ""}}
}
@@ -121,7 +123,7 @@
},
{"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
{
- {"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
+ {AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
{
{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
AUDIO_FLAG_BEACON, ""},
@@ -140,17 +142,17 @@
const engineConfig::ProductStrategies gOrderedSystemStrategies = {
{"rerouting",
{
- {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
+ {AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
- AUDIO_FLAG_NONE, ""}}
+ AUDIO_FLAG_NONE, AUDIO_TAG_APM_RESERVED_INTERNAL}}
}
},
},
{"patch",
{
- {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
+ {AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
{{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
- AUDIO_FLAG_NONE, ""}}
+ AUDIO_FLAG_NONE, AUDIO_TAG_APM_RESERVED_INTERNAL}}
}
},
}
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index fbfcf72..1d3ad1c 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -36,16 +36,16 @@
{
}
-void ProductStrategy::addAttributes(const AudioAttributes &audioAttributes)
+void ProductStrategy::addAttributes(const VolumeGroupAttributes &volumeGroupAttributes)
{
- mAttributesVector.push_back(audioAttributes);
+ mAttributesVector.push_back(volumeGroupAttributes);
}
-std::vector<android::AudioAttributes> ProductStrategy::listAudioAttributes() const
+std::vector<android::VolumeGroupAttributes> ProductStrategy::listVolumeGroupAttributes() const
{
- std::vector<android::AudioAttributes> androidAa;
+ std::vector<android::VolumeGroupAttributes> androidAa;
for (const auto &attr : mAttributesVector) {
- androidAa.push_back({attr.mVolumeGroup, attr.mStream, attr.mAttributes});
+ androidAa.push_back({attr.getGroupId(), attr.getStreamType(), attr.getAttributes()});
}
return androidAa;
}
@@ -54,7 +54,7 @@
{
AttributesVector attrVector;
for (const auto &attrGroup : mAttributesVector) {
- attrVector.push_back(attrGroup.mAttributes);
+ attrVector.push_back(attrGroup.getAttributes());
}
if (not attrVector.empty()) {
return attrVector;
@@ -62,52 +62,40 @@
return { AUDIO_ATTRIBUTES_INITIALIZER };
}
-bool ProductStrategy::matches(const audio_attributes_t attr) const
+int ProductStrategy::matchesScore(const audio_attributes_t attr) const
{
- return std::find_if(begin(mAttributesVector), end(mAttributesVector),
- [&attr](const auto &supportedAttr) {
- return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr);
- }) != end(mAttributesVector);
-}
-
-audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
- const audio_attributes_t &attr) const
-{
- const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
- [&attr](const auto &supportedAttr) {
- return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });
- if (iter == end(mAttributesVector)) {
- return AUDIO_STREAM_DEFAULT;
+ int strategyScore = AudioProductStrategy::NO_MATCH;
+ for (const auto &attrGroup : mAttributesVector) {
+ int score = AudioProductStrategy::attributesMatchesScore(attrGroup.getAttributes(), attr);
+ if (score == AudioProductStrategy::MATCH_EQUALS) {
+ return score;
+ }
+ strategyScore = std::max(score, strategyScore);
}
- audio_stream_type_t streamType = iter->mStream;
- ALOGW_IF(streamType == AUDIO_STREAM_DEFAULT,
- "%s: Strategy %s supporting attributes %s has not stream type associated"
- "fallback on MUSIC. Do not use stream volume API", __func__, mName.c_str(),
- toString(attr).c_str());
- return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
+ return strategyScore;
}
audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const
{
const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
[&streamType](const auto &supportedAttr) {
- return supportedAttr.mStream == streamType; });
- return iter != end(mAttributesVector) ? iter->mAttributes : AUDIO_ATTRIBUTES_INITIALIZER;
+ return supportedAttr.getStreamType() == streamType; });
+ return iter != end(mAttributesVector) ? iter->getAttributes() : AUDIO_ATTRIBUTES_INITIALIZER;
}
bool ProductStrategy::isDefault() const
{
return std::find_if(begin(mAttributesVector), end(mAttributesVector), [](const auto &attr) {
- return attr.mAttributes == defaultAttr; }) != end(mAttributesVector);
+ return attr.getAttributes() == defaultAttr; }) != end(mAttributesVector);
}
StreamTypeVector ProductStrategy::getSupportedStreams() const
{
StreamTypeVector streams;
for (const auto &supportedAttr : mAttributesVector) {
- if (std::find(begin(streams), end(streams), supportedAttr.mStream) == end(streams) &&
- supportedAttr.mStream != AUDIO_STREAM_DEFAULT) {
- streams.push_back(supportedAttr.mStream);
+ if (std::find(begin(streams), end(streams), supportedAttr.getStreamType())
+ == end(streams) && supportedAttr.getStreamType() != AUDIO_STREAM_DEFAULT) {
+ streams.push_back(supportedAttr.getStreamType());
}
}
return streams;
@@ -117,24 +105,14 @@
{
return std::find_if(begin(mAttributesVector), end(mAttributesVector),
[&streamType](const auto &supportedAttr) {
- return supportedAttr.mStream == streamType; }) != end(mAttributesVector);
-}
-
-volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
-{
- for (const auto &supportedAttr : mAttributesVector) {
- if (AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr)) {
- return supportedAttr.mVolumeGroup;
- }
- }
- return VOLUME_GROUP_NONE;
+ return supportedAttr.getStreamType() == streamType; }) != end(mAttributesVector);
}
volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
{
for (const auto &supportedAttr : mAttributesVector) {
- if (supportedAttr.mStream == stream) {
- return supportedAttr.mVolumeGroup;
+ if (supportedAttr.getStreamType() == stream) {
+ return supportedAttr.getGroupId();
}
}
return VOLUME_GROUP_NONE;
@@ -143,8 +121,10 @@
volume_group_t ProductStrategy::getDefaultVolumeGroup() const
{
const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
- [](const auto &attr) {return attr.mAttributes == defaultAttr;});
- return iter != end(mAttributesVector) ? iter->mVolumeGroup : VOLUME_GROUP_NONE;
+ [](const auto &attr) {
+ return attr.getAttributes() == defaultAttr;
+ });
+ return iter != end(mAttributesVector) ? iter->getGroupId() : VOLUME_GROUP_NONE;
}
void ProductStrategy::dump(String8 *dst, int spaces) const
@@ -155,26 +135,32 @@
deviceLiteral.c_str(), mDeviceAddress.c_str());
for (const auto &attr : mAttributesVector) {
- dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mVolumeGroup,
- android::toString(attr.mStream).c_str());
+ dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.getGroupId(),
+ android::toString(attr.getStreamType()).c_str());
dst->appendFormat("%*s Attributes: ", spaces + 3, "");
- std::string attStr =
- attr.mAttributes == defaultAttr ? "{ Any }" : android::toString(attr.mAttributes);
+ std::string attStr = attr.getAttributes() == defaultAttr ?
+ "{ Any }" : android::toString(attr.getAttributes());
dst->appendFormat("%s\n", attStr.c_str());
}
}
product_strategy_t ProductStrategyMap::getProductStrategyForAttributes(
- const audio_attributes_t &attr, bool fallbackOnDefault) const
+ const audio_attributes_t &attributes, bool fallbackOnDefault) const
{
+ product_strategy_t bestStrategyOrdefault = PRODUCT_STRATEGY_NONE;
+ int matchScore = AudioProductStrategy::NO_MATCH;
for (const auto &iter : *this) {
- if (iter.second->matches(attr)) {
+ int score = iter.second->matchesScore(attributes);
+ if (score == AudioProductStrategy::MATCH_EQUALS) {
return iter.second->getId();
}
+ if (score > matchScore) {
+ bestStrategyOrdefault = iter.second->getId();;
+ matchScore = score;
+ }
}
- ALOGV("%s: No matching product strategy for attributes %s, return default", __FUNCTION__,
- toString(attr).c_str());
- return fallbackOnDefault? getDefault() : PRODUCT_STRATEGY_NONE;
+ return (matchScore != AudioProductStrategy::MATCH_ON_DEFAULT_SCORE || fallbackOnDefault) ?
+ bestStrategyOrdefault : PRODUCT_STRATEGY_NONE;
}
audio_attributes_t ProductStrategyMap::getAttributesForStreamType(audio_stream_type_t stream) const
@@ -190,20 +176,6 @@
return {};
}
-audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
- const audio_attributes_t &attr) const
-{
- for (const auto &iter : *this) {
- audio_stream_type_t stream = iter.second->getStreamTypeForAttributes(attr);
- if (stream != AUDIO_STREAM_DEFAULT) {
- return stream;
- }
- }
- ALOGV("%s: No product strategy for attributes %s, using default (aka MUSIC)", __FUNCTION__,
- toString(attr).c_str());
- return AUDIO_STREAM_MUSIC;
-}
-
product_strategy_t ProductStrategyMap::getDefault() const
{
if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
@@ -268,16 +240,39 @@
return at(psId)->getDeviceAddress();
}
+VolumeGroupAttributes ProductStrategyMap::getVolumeGroupAttributesForAttributes(
+ const audio_attributes_t &attr, bool fallbackOnDefault) const
+{
+ int matchScore = AudioProductStrategy::NO_MATCH;
+ VolumeGroupAttributes bestVolumeGroupAttributes = {};
+ for (const auto &iter : *this) {
+ for (const auto &volGroupAttr : iter.second->getVolumeGroupAttributes()) {
+ int score = volGroupAttr.matchesScore(attr);
+ if (score == AudioProductStrategy::MATCH_EQUALS) {
+ return volGroupAttr;
+ }
+ if (score > matchScore) {
+ matchScore = score;
+ bestVolumeGroupAttributes = volGroupAttr;
+ }
+ }
+ }
+ return (matchScore != AudioProductStrategy::MATCH_ON_DEFAULT_SCORE || fallbackOnDefault) ?
+ bestVolumeGroupAttributes : VolumeGroupAttributes();
+}
+
+audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
+ const audio_attributes_t &attr) const
+{
+ audio_stream_type_t streamType = getVolumeGroupAttributesForAttributes(
+ attr, /* fallbackOnDefault= */ true).getStreamType();
+ return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
+}
+
volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(
const audio_attributes_t &attr, bool fallbackOnDefault) const
{
- for (const auto &iter : *this) {
- volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
- if (group != VOLUME_GROUP_NONE) {
- return group;
- }
- }
- return fallbackOnDefault ? getDefaultVolumeGroup() : VOLUME_GROUP_NONE;
+ return getVolumeGroupAttributesForAttributes(attr, fallbackOnDefault).getGroupId();
}
volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(
diff --git a/services/audiopolicy/engine/common/src/VolumeGroup.cpp b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
index e189807..f5ffbba 100644
--- a/services/audiopolicy/engine/common/src/VolumeGroup.cpp
+++ b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
@@ -37,6 +37,17 @@
{
}
+// Used for introspection, e.g. JAVA
+AttributesVector VolumeGroup::getSupportedAttributes() const
+{
+ AttributesVector supportedAttributes = {};
+ for (auto &aa : mGroupVolumeCurves.getAttributes()) {
+ aa.source = AUDIO_SOURCE_INVALID;
+ supportedAttributes.push_back(aa);
+ }
+ return supportedAttributes;
+}
+
void VolumeGroup::dump(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index 459cc78..12597de 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -22,11 +22,13 @@
"-Wextra",
],
shared_libs: [
- "libmedia_helper",
- "libxml2",
- "libutils",
- "liblog",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudiopolicycomponents",
"libcutils",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ "libxml2",
],
header_libs: [
"libaudio_system_headers",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 2ebb7df..119dbd6 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -16,15 +16,22 @@
#pragma once
-#include <system/audio.h>
-
#include <string>
#include <vector>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio.h>
#include <utils/Errors.h>
struct _xmlNode;
struct _xmlDoc;
+/**
+ * AudioAttributes custom tag to identify internal strategies, whose volumes are exclusively
+ * controlled by AudioPolicyManager
+ */
+#define AUDIO_TAG_APM_RESERVED_INTERNAL "reserved_internal_strategy"
+
namespace android {
namespace engineConfig {
@@ -35,7 +42,6 @@
using StreamVector = std::vector<audio_stream_type_t>;
struct AttributesGroup {
- std::string name;
audio_stream_type_t stream;
std::string volumeGroup;
AttributesVector attributesVect;
@@ -111,6 +117,7 @@
*/
ParsingResult parse(const char* path = DEFAULT_PATH);
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups);
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
// Exposed for testing.
android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups);
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 6f560d5..ca78ce7 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -14,26 +14,30 @@
* limitations under the License.
*/
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
#define LOG_TAG "APM::AudioPolicyEngine/Config"
//#define LOG_NDEBUG 0
#include "EngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
#include <cutils/properties.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
#include <media/TypeConverter.h>
#include <media/convert.h>
#include <system/audio_config.h>
#include <utils/Log.h>
-#include <libxml/parser.h>
-#include <libxml/xinclude.h>
-#include <string>
-#include <vector>
-#include <map>
-#include <sstream>
-#include <istream>
-
-#include <cstdint>
-#include <stdarg.h>
-#include <string>
namespace android {
@@ -45,6 +49,85 @@
static const char *const gReferenceElementName = "reference";
static const char *const gReferenceAttributeName = "name";
+namespace {
+
+ConversionResult<AttributesGroup> aidl2legacy_AudioHalAttributeGroup_AttributesGroup(
+ const media::audio::common::AudioHalAttributesGroup& aidl) {
+ AttributesGroup legacy;
+ legacy.stream = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+ legacy.volumeGroup = aidl.volumeGroupName;
+ legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
+ aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
+ return legacy;
+}
+
+ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
+ const media::audio::common::AudioHalProductStrategy& aidl) {
+ ProductStrategy legacy;
+ legacy.name = "strategy_" + std::to_string(aidl.id);
+ legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
+ aidl.attributesGroups,
+ aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
+ return legacy;
+}
+
+ConversionResult<std::string> legacy_device_category_to_string(device_category legacy) {
+ std::string s;
+ if (DeviceCategoryConverter::toString(legacy, s)) {
+ return s;
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::string> aidl2legacy_DeviceCategory(
+ const media::audio::common::AudioHalVolumeCurve::DeviceCategory aidl) {
+ using DeviceCategory = media::audio::common::AudioHalVolumeCurve::DeviceCategory;
+ switch (aidl) {
+ case DeviceCategory::HEADSET:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_HEADSET);
+ case DeviceCategory::SPEAKER:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_SPEAKER);
+ case DeviceCategory::EARPIECE:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_EARPIECE);
+ case DeviceCategory::EXT_MEDIA:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_EXT_MEDIA);
+ case DeviceCategory::HEARING_AID:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_HEARING_AID);
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<CurvePoint> aidl2legacy_AudioHalCurvePoint_CurvePoint(
+ const media::audio::common::AudioHalVolumeCurve::CurvePoint& aidl) {
+ CurvePoint legacy;
+ legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+ legacy.attenuationInMb = aidl.attenuationMb;
+ return legacy;
+}
+
+ConversionResult<VolumeCurve> aidl2legacy_AudioHalVolumeCurve_VolumeCurve(
+ const media::audio::common::AudioHalVolumeCurve& aidl) {
+ VolumeCurve legacy;
+ legacy.deviceCategory = VALUE_OR_RETURN(aidl2legacy_DeviceCategory(aidl.deviceCategory));
+ legacy.curvePoints = VALUE_OR_RETURN(convertContainer<CurvePoints>(
+ aidl.curvePoints, aidl2legacy_AudioHalCurvePoint_CurvePoint));
+ return legacy;
+}
+
+ConversionResult<VolumeGroup> aidl2legacy_AudioHalVolumeGroup_VolumeGroup(
+ const media::audio::common::AudioHalVolumeGroup& aidl) {
+ VolumeGroup legacy;
+ legacy.name = aidl.name;
+ legacy.indexMin = aidl.minIndex;
+ legacy.indexMax = aidl.maxIndex;
+ legacy.volumeCurves = VALUE_OR_RETURN(convertContainer<VolumeCurves>(
+ aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
+ return legacy;
+}
+
+} // namespace
+
template<typename E, typename C>
struct BaseSerializerTraits {
typedef E Element;
@@ -57,7 +140,6 @@
static constexpr const char *collectionTag = "AttributesGroups";
struct Attributes {
- static constexpr const char *name = "name";
static constexpr const char *streamType = "streamType";
static constexpr const char *volumeGroup = "volumeGroup";
};
@@ -313,12 +395,6 @@
status_t AttributesGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
Collection &attributesGroup)
{
- std::string name = getXmlAttribute(child, Attributes::name);
- if (name.empty()) {
- ALOGV("AttributesGroupTraits No attribute %s found", Attributes::name);
- }
- ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
-
std::string volumeGroup = getXmlAttribute(child, Attributes::volumeGroup);
if (volumeGroup.empty()) {
ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::volumeGroup);
@@ -339,7 +415,7 @@
AttributesVector attributesVect;
deserializeAttributesCollection(doc, child, attributesVect);
- attributesGroup.push_back({name, streamType, volumeGroup, attributesVect});
+ attributesGroup.push_back({streamType, volumeGroup, attributesVect});
return NO_ERROR;
}
@@ -731,5 +807,25 @@
}
}
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ auto config = std::make_unique<engineConfig::Config>();
+ config->version = 1.0f;
+ if (auto conv = convertContainer<engineConfig::ProductStrategies>(
+ aidlConfig.productStrategies,
+ aidl2legacy_AudioHalProductStrategy_ProductStrategy); conv.ok()) {
+ config->productStrategies = std::move(conv.value());
+ } else {
+ return ParsingResult{};
+ }
+ if (auto conv = convertContainer<engineConfig::VolumeGroups>(
+ aidlConfig.volumeGroups,
+ aidl2legacy_AudioHalVolumeGroup_VolumeGroup); conv.ok()) {
+ config->volumeGroups = std::move(conv.value());
+ } else {
+ return ParsingResult{};
+ }
+ return {.parsedConfig=std::move(config), .nbSkippedElement=0};
+ }
+
} // namespace engineConfig
} // namespace android
diff --git a/services/audiopolicy/engine/config/tests/Android.bp b/services/audiopolicy/engine/config/tests/Android.bp
index 5791f17..5d1aa16 100644
--- a/services/audiopolicy/engine/config/tests/Android.bp
+++ b/services/audiopolicy/engine/config/tests/Android.bp
@@ -11,6 +11,7 @@
name: "audiopolicy_engineconfig_tests",
shared_libs: [
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libmedia_helper",
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index 9c156ab..5c37409 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -20,6 +20,7 @@
#include <utility>
#include <AudioPolicyManagerObserver.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <IVolumeCurves.h>
@@ -47,6 +48,14 @@
{
public:
/**
+ * Loads the engine configuration from AIDL configuration data.
+ * If loading failed, tries to fall back to some default configuration. If fallback
+ * is impossible, returns an error.
+ */
+ virtual status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) = 0;
+
+ /**
* Loads the engine configuration from the specified or the default config file.
* If loading failed, tries to fall back to some default configuration. If fallback
* is impossible, returns an error.
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index dc8d9cf..eb2e2f4 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -35,14 +35,15 @@
"libaudiopolicyengineconfigurable_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
"libaudiopolicyengineconfigurable_pfwwrapper",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libcutils",
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index 0398fc7..f7159c5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -31,11 +31,11 @@
"libaudiopolicyengineconfigurable_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libpfw_utility",
],
shared_libs: [
+ "libaudiopolicycomponents",
"libaudiopolicyengineconfigurable",
"liblog",
"libutils",
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 257d1fc..f07ce82 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -70,6 +70,12 @@
{
}
+status_t Engine::loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config __unused) {
+ // b/242678729. Need to implement for the configurable engine.
+ return INVALID_OPERATION;
+}
+
status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
{
status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
@@ -92,7 +98,7 @@
template <typename Key>
Element<Key> *Engine::getFromCollection(const Key &key) const
{
- const Collection<Key> collection = getCollection<Key>();
+ const Collection<Key> &collection = getCollection<Key>();
return collection.get(key);
}
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index d5083f0..903ab34 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -41,12 +41,15 @@
///
/// from EngineInterface
///
- android::status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+ status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) override;
+
+ status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
///
/// from EngineBase
///
- android::status_t initCheck() override;
+ status_t initCheck() override;
status_t setPhoneState(audio_mode_t mode) override;
@@ -56,8 +59,8 @@
audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const override;
- android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
- audio_policy_dev_state_t state) override;
+ status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state) override;
DeviceVector getOutputDevicesForAttributes(const audio_attributes_t &attr,
const sp<DeviceDescriptor> &preferedDevice = nullptr,
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index 4671fe9..7d4ccab 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -25,12 +25,13 @@
"libaudiopolicyengine_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libcutils",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 0fa0e0e..e2f42da 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -35,10 +35,7 @@
#include <utils/String8.h>
#include <utils/Log.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android::audio_policy {
struct legacy_strategy_map { const char *name; legacy_strategy id; };
static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
@@ -59,8 +56,18 @@
return legacyStrategy;
}
+status_t Engine::loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ return loadWithFallback(aidlConfig);
+}
+
status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
- auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
+ return loadWithFallback(xmlFilePath);
+}
+
+template<typename T>
+status_t Engine::loadWithFallback(const T& configSource) {
+ auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
ALOGE_IF(result.nbSkippedElement != 0,
"Policy Engine configuration is partially invalid, skipped %zu elements",
result.nbSkippedElement);
@@ -73,6 +80,7 @@
return OK;
}
+
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
switch(usage) {
@@ -794,5 +802,4 @@
AUDIO_FORMAT_DEFAULT);
}
-} // namespace audio_policy
-} // namespace android
+} // namespace android::audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index fde9802..66225a1 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -47,10 +47,14 @@
public:
Engine() = default;
virtual ~Engine() = default;
+ Engine(const Engine &object) = delete;
+ Engine &operator=(const Engine &object) = delete;
///
/// from EngineInterface
///
+ status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) override;
status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
private:
@@ -78,9 +82,8 @@
DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
private:
- /* Copy facilities are put private to disable copy. */
- Engine(const Engine &object);
- Engine &operator=(const Engine &object);
+ template<typename T>
+ status_t loadWithFallback(const T& configSource);
status_t setDefaultDevice(audio_devices_t device);
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 621f643..c4b3751 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -38,6 +38,7 @@
"capture_state_listener-aidl-cpp",
"libaudioclient",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"libcutils",
"libhidlbase",
@@ -54,7 +55,6 @@
],
static_libs: [
"android.hardware.audio.common@7.0-enums",
- "libaudiopolicycomponents",
],
header_libs: [
"libaudiopolicycommon",
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 6e34eb0..a1785da 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -23,6 +23,7 @@
shared_libs: [
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libcutils",
"libdl",
"libutils",
@@ -49,8 +50,6 @@
"libaudiopolicymanager_interface_headers",
],
- static_libs: ["libaudiopolicycomponents"],
-
cflags: [
"-Wall",
"-Werror",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8154944..b7abef9 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -5705,10 +5705,14 @@
if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
continue;
}
- hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
- ALOGW("could not open HW module %s", hwModule->getName());
- continue;
+ if (audio_module_handle_t handle = mpClientInterface->loadHwModule(hwModule->getName());
+ handle != AUDIO_MODULE_HANDLE_NONE) {
+ hwModule->setHandle(handle);
+ } else {
+ ALOGW("could not load HW module %s", hwModule->getName());
+ continue;
+ }
}
mHwModules.push_back(hwModule);
// open all output streams needed to access attached devices.
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index bb41f85..0de5c0e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -361,11 +361,10 @@
}
virtual status_t getProductStrategyFromAudioAttributes(
- const AudioAttributes &aa, product_strategy_t &productStrategy,
+ const audio_attributes_t &aa, product_strategy_t &productStrategy,
bool fallbackOnDefault)
{
- productStrategy = mEngine->getProductStrategyForAttributes(
- aa.getAttributes(), fallbackOnDefault);
+ productStrategy = mEngine->getProductStrategyForAttributes(aa, fallbackOnDefault);
return (fallbackOnDefault && productStrategy == PRODUCT_STRATEGY_NONE) ?
BAD_VALUE : NO_ERROR;
}
@@ -376,10 +375,9 @@
}
virtual status_t getVolumeGroupFromAudioAttributes(
- const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault)
+ const audio_attributes_t &aa, volume_group_t &volumeGroup, bool fallbackOnDefault)
{
- volumeGroup = mEngine->getVolumeGroupForAttributes(
- aa.getAttributes(), fallbackOnDefault);
+ volumeGroup = mEngine->getVolumeGroupForAttributes(aa, fallbackOnDefault);
return (fallbackOnDefault && volumeGroup == VOLUME_GROUP_NONE) ?
BAD_VALUE : NO_ERROR;
}
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index 939fbc5..ab77941 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -40,6 +40,23 @@
return engine;
}
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const media::audio::common::AudioHalEngineConfig& config)
+{
+ auto engLib = EngineLibrary::load(librarySuffix);
+ if (!engLib) {
+ ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
+ __func__, librarySuffix.c_str());
+ return nullptr;
+ }
+ auto engine = engLib->createEngineUsingHalConfig(config);
+ if (engine == nullptr) {
+ ALOGE("%s: Failed to instantiate the APM engine", __func__);
+ return nullptr;
+ }
+ return engine;
+}
+
// static
std::shared_ptr<EngineLibrary> EngineLibrary::load(const std::string& librarySuffix)
{
@@ -53,7 +70,8 @@
close();
}
-EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath) {
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath)
+{
auto instance = createEngine();
if (instance != nullptr) {
if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
@@ -67,6 +85,21 @@
return nullptr;
}
+EngineInstance EngineLibrary::createEngineUsingHalConfig(
+ const media::audio::common::AudioHalEngineConfig& config)
+{
+ auto instance = createEngine();
+ if (instance != nullptr) {
+ if (status_t status = instance->loadFromHalConfigWithFallback(config); status == OK) {
+ return instance;
+ } else {
+ ALOGE("%s: loading of the engine config with HAL configuration \"%s\" failed: %d",
+ __func__, config.toString().c_str(), status);
+ }
+ }
+ return nullptr;
+}
+
bool EngineLibrary::init(std::string libraryPath)
{
mLibraryHandle = dlopen(libraryPath.c_str(), 0);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
index dc138a1..4710e34 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -21,6 +21,7 @@
#include <string>
#include <EngineInterface.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
namespace android {
@@ -28,6 +29,8 @@
EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
const std::string& configXmlFilePath = "");
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const media::audio::common::AudioHalEngineConfig& config);
class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
public:
@@ -40,6 +43,8 @@
EngineLibrary& operator=(EngineLibrary&&) = delete;
EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
+ EngineInstance createEngineUsingHalConfig(
+ const media::audio::common::AudioHalEngineConfig& config);
private:
EngineLibrary() = default;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 8c541f6..734bf9e 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -35,6 +35,7 @@
"libaudiofoundation",
"libaudiohal",
"libaudiopolicy",
+ "libaudiopolicycomponents",
"libaudiopolicymanagerdefault",
"libaudioutils",
"libbinder",
@@ -65,7 +66,6 @@
],
static_libs: [
- "libaudiopolicycomponents",
"framework-permission-aidl-cpp",
],
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 4691135..290db97 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -27,6 +27,18 @@
/* implementation of the client interface from the policy manager */
+status_t AudioPolicyService::AudioPolicyClient::getAudioPolicyConfig(
+ media::AudioPolicyConfig *config)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return AUDIO_MODULE_HANDLE_NONE;
+ }
+
+ return af->getAudioPolicyConfig(config);
+}
+
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index b111865..70a1785 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -924,8 +924,7 @@
for (auto& stream : processingChain) {
auto effectDescs = std::make_unique<EffectDescVector>();
for (auto& effect : stream.effects) {
- effectDescs->mEffects.add(
- new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+ effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
}
streams.add(stream.type, effectDescs.release());
}
@@ -935,8 +934,7 @@
for (auto& deviceProcess : processingChain) {
auto effectDescs = std::make_unique<EffectDescVector>();
for (auto& effect : deviceProcess.effects) {
- effectDescs->mEffects.add(
- new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+ effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
}
auto deviceEffects = std::make_unique<DeviceEffects>(
std::move(effectDescs), deviceProcess.type, deviceProcess.address);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 0df3962..91857f9 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -317,7 +317,7 @@
return Status::ok();
}
-Status AudioPolicyService::getOutputForAttr(const media::AudioAttributesInternal& attrAidl,
+Status AudioPolicyService::getOutputForAttr(const media::audio::common::AudioAttributes& attrAidl,
int32_t sessionAidl,
const AttributionSourceState& attributionSource,
const AudioConfig& configAidl,
@@ -326,7 +326,7 @@
media::GetOutputForAttrResponse* _aidl_return)
{
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_session_t(sessionAidl));
audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
@@ -554,7 +554,7 @@
mAudioPolicyManager->releaseOutput(portId);
}
-Status AudioPolicyService::getInputForAttr(const media::AudioAttributesInternal& attrAidl,
+Status AudioPolicyService::getInputForAttr(const media::audio::common::AudioAttributes& attrAidl,
int32_t inputAidl,
int32_t riidAidl,
int32_t sessionAidl,
@@ -564,7 +564,7 @@
int32_t selectedDeviceIdAidl,
media::GetInputForAttrResponse* _aidl_return) {
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_io_handle_t input = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(inputAidl));
audio_unique_id_t riid = VALUE_OR_RETURN_BINDER_STATUS(
@@ -1026,10 +1026,10 @@
}
Status AudioPolicyService::setVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
const AudioDeviceDescription& deviceAidl, int32_t indexAidl) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
@@ -1049,10 +1049,10 @@
}
Status AudioPolicyService::getVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
const AudioDeviceDescription& deviceAidl, int32_t* _aidl_return) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
int index;
@@ -1071,9 +1071,9 @@
}
Status AudioPolicyService::getMinVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl, int32_t* _aidl_return) {
+ const media::audio::common::AudioAttributes& attrAidl, int32_t* _aidl_return) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1090,9 +1090,9 @@
}
Status AudioPolicyService::getMaxVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl, int32_t* _aidl_return) {
+ const media::audio::common::AudioAttributes& attrAidl, int32_t* _aidl_return) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1130,12 +1130,13 @@
return Status::ok();
}
-Status AudioPolicyService::getDevicesForAttributes(const media::AudioAttributesEx& attrAidl,
- bool forVolume,
- std::vector<AudioDevice>* _aidl_return)
+Status AudioPolicyService::getDevicesForAttributes(
+ const media::audio::common::AudioAttributes& attrAidl,
+ bool forVolume,
+ std::vector<AudioDevice>* _aidl_return)
{
- AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesEx_AudioAttributes(attrAidl));
+ audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
AudioDeviceTypeAddrVector devices;
if (mAudioPolicyManager == NULL) {
@@ -1144,8 +1145,7 @@
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
- mAudioPolicyManager->getDevicesForAttributes(
- aa.getAttributes(), &devices, forVolume)));
+ mAudioPolicyManager->getDevicesForAttributes(aa, &devices, forVolume)));
*_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
convertContainer<std::vector<AudioDevice>>(devices,
legacy2aidl_AudioDeviceTypeAddress));
@@ -1461,12 +1461,12 @@
Status AudioPolicyService::isDirectOutputSupported(
const AudioConfigBase& configAidl,
- const media::AudioAttributesInternal& attributesAidl,
+ const media::audio::common::AudioAttributes& attributesAidl,
bool* _aidl_return) {
audio_config_base_t config = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioConfigBase_audio_config_base_t(configAidl, false /*isInput*/));
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attributesAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attributesAidl));
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1783,12 +1783,12 @@
}
Status AudioPolicyService::startAudioSource(const media::AudioPortConfigFw& sourceAidl,
- const media::AudioAttributesInternal& attributesAidl,
- int32_t* _aidl_return) {
+ const media::audio::common::AudioAttributes& attributesAidl,
+ int32_t* _aidl_return) {
audio_port_config source = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPortConfigFw_audio_port_config(sourceAidl));
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attributesAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attributesAidl));
audio_port_handle_t portId;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
AudioValidator::validateAudioPortConfig(source)));
@@ -2050,9 +2050,10 @@
}
Status AudioPolicyService::getProductStrategyFromAudioAttributes(
- const media::AudioAttributesEx& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) {
- AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesEx_AudioAttributes(aaAidl));
+ const media::audio::common::AudioAttributes& aaAidl,
+ bool fallbackOnDefault, int32_t* _aidl_return) {
+ audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl));
product_strategy_t productStrategy;
if (mAudioPolicyManager == NULL) {
@@ -2083,9 +2084,10 @@
}
Status AudioPolicyService::getVolumeGroupFromAudioAttributes(
- const media::AudioAttributesEx& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) {
- AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesEx_AudioAttributes(aaAidl));
+ const media::audio::common::AudioAttributes& aaAidl,
+ bool fallbackOnDefault, int32_t* _aidl_return) {
+ audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
+ aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl));
volume_group_t volumeGroup;
if (mAudioPolicyManager == NULL) {
@@ -2299,7 +2301,7 @@
}
Status AudioPolicyService::canBeSpatialized(
- const std::optional<media::AudioAttributesInternal>& attrAidl,
+ const std::optional<media::audio::common::AudioAttributes>& attrAidl,
const std::optional<AudioConfig>& configAidl,
const std::vector<AudioDevice>& devicesAidl,
bool* _aidl_return) {
@@ -2309,7 +2311,7 @@
audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
if (attrAidl.has_value()) {
attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl.value()));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl.value()));
}
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
if (configAidl.has_value()) {
@@ -2326,9 +2328,10 @@
return Status::ok();
}
-Status AudioPolicyService::getDirectPlaybackSupport(const media::AudioAttributesInternal &attrAidl,
- const AudioConfig &configAidl,
- media::AudioDirectMode *_aidl_return) {
+Status AudioPolicyService::getDirectPlaybackSupport(
+ const media::audio::common::AudioAttributes &attrAidl,
+ const AudioConfig &configAidl,
+ media::AudioDirectMode *_aidl_return) {
if (mAudioPolicyManager == nullptr) {
return binderStatusFromStatusT(NO_INIT);
}
@@ -2336,7 +2339,7 @@
return binderStatusFromStatusT(BAD_VALUE);
}
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_config_t config = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioConfig_audio_config_t(configAidl, false /*isInput*/));
Mutex::Autolock _l(mLock);
@@ -2347,13 +2350,13 @@
}
Status AudioPolicyService::getDirectProfilesForAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
std::vector<media::audio::common::AudioProfile>* _aidl_return) {
if (mAudioPolicyManager == nullptr) {
return binderStatusFromStatusT(NO_INIT);
}
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
AudioProfileVector audioProfiles;
Mutex::Autolock _l(mLock);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 930631a..50c2c46 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -180,10 +180,23 @@
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
- auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
- AudioPolicyManager *apm = new AudioPolicyManager(
- config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
- clientInterface);
+ AudioPolicyManager *apm = nullptr;
+ media::AudioPolicyConfig apmConfig;
+ if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
+ auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
+ LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
+ AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
+ "Only default engine is currently supported with the AIDL HAL");
+ apm = new AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(
+ config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
+ clientInterface);
+ } else {
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
+ apm = new AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+ clientInterface);
+ }
status_t status = apm->initialize();
if (status != NO_ERROR) {
delete apm;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index a101309..8c85bff 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -69,7 +69,7 @@
public IBinder::DeathRecipient,
public SpatializerPolicyCallback
{
- friend class BinderService<AudioPolicyService>;
+ friend class sp<AudioPolicyService>;
public:
// for BinderService
@@ -97,7 +97,8 @@
binder::Status getForceUse(media::AudioPolicyForceUse usage,
media::AudioPolicyForcedConfig* _aidl_return) override;
binder::Status getOutput(AudioStreamType stream, int32_t* _aidl_return) override;
- binder::Status getOutputForAttr(const media::AudioAttributesInternal& attr, int32_t session,
+ binder::Status getOutputForAttr(const media::audio::common::AudioAttributes& attr,
+ int32_t session,
const AttributionSourceState &attributionSource,
const AudioConfig& config,
int32_t flags, int32_t selectedDeviceId,
@@ -105,7 +106,7 @@
binder::Status startOutput(int32_t portId) override;
binder::Status stopOutput(int32_t portId) override;
binder::Status releaseOutput(int32_t portId) override;
- binder::Status getInputForAttr(const media::AudioAttributesInternal& attr, int32_t input,
+ binder::Status getInputForAttr(const media::audio::common::AudioAttributes& attr, int32_t input,
int32_t riid, int32_t session,
const AttributionSourceState &attributionSource,
const AudioConfigBase& config, int32_t flags,
@@ -122,19 +123,19 @@
binder::Status getStreamVolumeIndex(AudioStreamType stream,
const AudioDeviceDescription& device,
int32_t* _aidl_return) override;
- binder::Status setVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status setVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
const AudioDeviceDescription& device,
int32_t index) override;
- binder::Status getVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
const AudioDeviceDescription& device,
int32_t* _aidl_return) override;
- binder::Status getMaxVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getMaxVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
int32_t* _aidl_return) override;
- binder::Status getMinVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getMinVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
int32_t* _aidl_return) override;
binder::Status getStrategyForStream(AudioStreamType stream,
int32_t* _aidl_return) override;
- binder::Status getDevicesForAttributes(const media::AudioAttributesEx& attr,
+ binder::Status getDevicesForAttributes(const media::audio::common::AudioAttributes& attr,
bool forVolume,
std::vector<AudioDevice>* _aidl_return) override;
binder::Status getOutputForEffect(const media::EffectDescriptor& desc,
@@ -169,7 +170,7 @@
binder::Status getOffloadSupport(const media::audio::common::AudioOffloadInfo& info,
media::AudioOffloadMode* _aidl_return) override;
binder::Status isDirectOutputSupported(const AudioConfigBase& config,
- const media::AudioAttributesInternal& attributes,
+ const media::audio::common::AudioAttributes& attributes,
bool* _aidl_return) override;
binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
Int* count, std::vector<media::AudioPortFw>* ports,
@@ -200,7 +201,7 @@
const std::vector<AudioDevice>& devices) override;
binder::Status removeUserIdDeviceAffinities(int32_t userId) override;
binder::Status startAudioSource(const media::AudioPortConfigFw& source,
- const media::AudioAttributesInternal& attributes,
+ const media::audio::common::AudioAttributes& attributes,
int32_t* _aidl_return) override;
binder::Status stopAudioSource(int32_t portId) override;
binder::Status setMasterMono(bool mono) override;
@@ -226,14 +227,16 @@
binder::Status isUltrasoundSupported(bool* _aidl_return) override;
binder::Status listAudioProductStrategies(
std::vector<media::AudioProductStrategy>* _aidl_return) override;
- binder::Status getProductStrategyFromAudioAttributes(const media::AudioAttributesEx& aa,
- bool fallbackOnDefault,
- int32_t* _aidl_return) override;
+ binder::Status getProductStrategyFromAudioAttributes(
+ const media::audio::common::AudioAttributes& aa,
+ bool fallbackOnDefault,
+ int32_t* _aidl_return) override;
binder::Status listAudioVolumeGroups(
std::vector<media::AudioVolumeGroup>* _aidl_return) override;
- binder::Status getVolumeGroupFromAudioAttributes(const media::AudioAttributesEx& aa,
- bool fallbackOnDefault,
- int32_t* _aidl_return) override;
+ binder::Status getVolumeGroupFromAudioAttributes(
+ const media::audio::common::AudioAttributes& aa,
+ bool fallbackOnDefault,
+ int32_t* _aidl_return) override;
binder::Status setRttEnabled(bool enabled) override;
binder::Status isCallScreenModeSupported(bool* _aidl_return) override;
binder::Status setDevicesRoleForStrategy(
@@ -267,16 +270,16 @@
binder::Status getSpatializer(const sp<media::INativeSpatializerCallback>& callback,
media::GetSpatializerResponse* _aidl_return) override;
binder::Status canBeSpatialized(
- const std::optional<media::AudioAttributesInternal>& attr,
+ const std::optional<media::audio::common::AudioAttributes>& attr,
const std::optional<AudioConfig>& config,
const std::vector<AudioDevice>& devices,
bool* _aidl_return) override;
- binder::Status getDirectPlaybackSupport(const media::AudioAttributesInternal& attr,
+ binder::Status getDirectPlaybackSupport(const media::audio::common::AudioAttributes& attr,
const AudioConfig& config,
media::AudioDirectMode* _aidl_return) override;
- binder::Status getDirectProfilesForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getDirectProfilesForAttributes(const media::audio::common::AudioAttributes& attr,
std::vector<media::audio::common::AudioProfile>* _aidl_return) override;
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
@@ -707,6 +710,8 @@
explicit AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {}
virtual ~AudioPolicyClient() {}
+ virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig *config);
+
//
// Audio HW module functions
//
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 8499c1c..b9ee8dd 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -74,6 +74,7 @@
"libaudioclient",
"libaudioclient_aidl_conversion",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libaudiopolicymanagerdefault",
"libcutils",
"liblog",
@@ -85,8 +86,6 @@
"libxml2",
],
- static_libs: ["libaudiopolicycomponents"],
-
header_libs: [
"libaudiopolicyengine_interface_headers",
"libaudiopolicymanager_interface_headers",
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index e81a3b5..b212a32 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -25,6 +25,9 @@
virtual ~AudioPolicyTestClient() = default;
// AudioPolicyClientInterface Implementation
+ status_t getAudioPolicyConfig(media::AudioPolicyConfig* /*config*/) override {
+ return INVALID_OPERATION;
+ }
audio_module_handle_t loadHwModule(const char* /*name*/) override {
return AUDIO_MODULE_HANDLE_NONE;
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index c72986d..4259efd 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -2292,7 +2292,11 @@
const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider,
const std::vector<std::string>& publicCameraIds) :
- DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
+ DeviceInfo(name, tagId, id,
+ hardware::hidl_version{
+ static_cast<uint16_t >(
+ parentProvider->getIPCTransport() == IPCTransport::HIDL ? 3 : 1),
+ minorVersion},
publicCameraIds, resourceCost, parentProvider) { }
void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(int64_t newState) {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index e43b91f..4986199 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -29,11 +29,8 @@
],
}
-cc_fuzz {
- name: "camera_service_fuzzer",
- srcs: [
- "camera_service_fuzzer.cpp",
- ],
+cc_defaults {
+ name: "camera_service_fuzzer_defaults",
header_libs: [
"libmedia_headers",
],
@@ -73,3 +70,28 @@
},
}
+
+cc_fuzz {
+ name: "camera_service_fuzzer",
+ srcs: [
+ "camera_service_fuzzer.cpp",
+ ],
+ defaults: [
+ "camera_service_fuzzer_defaults"
+ ],
+}
+
+cc_fuzz {
+ name: "camera_service_aidl_fuzzer",
+ srcs: [
+ "camera_service_aidl_fuzzer.cpp",
+ ],
+ defaults: [
+ "camera_service_fuzzer_defaults",
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ ],
+ fuzz_config: {
+ triage_assignee: "waghpawan@google.com",
+ },
+}
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp
new file mode 100644
index 0000000..a0fb93c
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 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 <fuzzbinder/libbinder_driver.h>
+#include <CameraService.h>
+
+using android::fuzzService;
+using android::sp;
+using android::CameraService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<CameraService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 20a6378..99703e3 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -27,13 +27,8 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_fuzz {
- name: "mediametrics_service_fuzzer",
-
- srcs: [
- "mediametrics_service_fuzzer.cpp",
- ],
-
+cc_defaults {
+ name: "mediametrics_service_fuzzer_defaults",
static_libs: [
"libmediametrics",
"libmediametricsservice",
@@ -78,3 +73,26 @@
fuzzed_code_usage: "shipped",
},
}
+
+cc_fuzz {
+ name: "mediametrics_service_fuzzer",
+
+ srcs: [
+ "mediametrics_service_fuzzer.cpp",
+ ],
+ defaults: [
+ "mediametrics_service_fuzzer_defaults",
+ ],
+}
+
+cc_fuzz {
+ name: "mediametrics_aidl_fuzzer",
+ srcs: [
+ "mediametrics_aidl_fuzzer.cpp",
+ ],
+ defaults: [
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ "mediametrics_service_fuzzer_defaults",
+ ],
+}
diff --git a/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
new file mode 100644
index 0000000..c7468c7
--- /dev/null
+++ b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 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 <fuzzbinder/libbinder_driver.h>
+
+#include <mediametricsservice/MediaMetricsService.h>
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaMetricsService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<MediaMetricsService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}