From 625225c36dd022f9f478100fbc0a4a33b4b0fe8a Mon Sep 17 00:00:00 2001 From: Haynes Mathew George Date: Tue, 24 Jan 2017 20:06:05 -0800 Subject: [PATCH 001/148] audioflinger: pause direct output when buffer timeout Previously, direct output can be paused when underrun is observed for the first time, this can interrupt the playback even there is PCM data cached in the driver, and underrun may be recovered within on the next loop cycle. Pausing the HAL is unnecessary at this time. Only do HAL pausing when track is going to be removed for buffer timeout, allow the client to fill the buffer for the next loop cycle. Test: directed test (see b/186596553) Bug: 34711969 Bug: 157682459 Bug: 161089206 Bug: 186596553 authored-by: Zhou Song Merged-In: I3707d883d0daa4ffd2baa9bd69aebf4bf9ddef4e Change-Id: I3707d883d0daa4ffd2baa9bd69aebf4bf9ddef4e (cherry picked from commit 82fa4811144a3aaf6c7897507e351123fabb3811) --- services/audioflinger/Threads.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 2af27d8a30..21661b0ce5 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -5941,15 +5941,17 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available track->disable(); - } else if (last) { + // only do hw pause when track is going to be removed due to BUFFER TIMEOUT. + // unlike mixerthread, HAL can be paused for direct output ALOGW("pause because of UNDERRUN, framesReady = %zu," "minFrames = %u, mFormat = %#x", framesReady, minFrames, mFormat); - mixerStatus = MIXER_TRACKS_ENABLED; - if (mHwSupportsPause && !mHwPaused && !mStandby) { + if (last && mHwSupportsPause && !mHwPaused && !mStandby) { doHwPause = true; mHwPaused = true; } + } else if (last) { + mixerStatus = MIXER_TRACKS_ENABLED; } } } From 741c347b6cd6a216077725be567e5708dce96594 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Fri, 5 May 2023 17:36:39 -0700 Subject: [PATCH 002/148] APM: Implementing configuration loading from AIDL HAL The main change is to utilize 'getAudioPolicyConfig' to receive the HAL-provided configuration from the AudioFlinger and initialize runtime structures from it. Accompanying changes: - made `libaudiopolicycomponents` a shared library; - added or moved around necessary conversion functions; Bug: 205884982 Test: run CF with AIDL HAL and compare APM dump A/B Test: m audiopolicy_fuzzer Test: atest audio_health_tests Test: atest audio_aidl_ndk_conversion_tests (cherry picked from https://android-review.googlesource.com/q/commit:9e459d7393179e7df286601c7536210c6011f090) Merged-In: I7d0f48bf4d9d4bdaa46246aa4dfbcc49e835c6b6 Change-Id: I7d0f48bf4d9d4bdaa46246aa4dfbcc49e835c6b6 --- .../AidlConversionCppNdk.cpp | 190 ++++++++++++++++++ .../include/media/AidlConversionCppNdk-impl.h | 12 ++ .../include/media/AidlConversionUtil-impl.h | 42 ++++ .../tests/audio_aidl_ndk_conversion_tests.cpp | 40 ++++ .../audio_aidl_ndk_cpp_conversion_tests.cpp | 9 + media/libaudiohal/impl/DeviceHalAidl.cpp | 7 +- .../common/managerdefinitions/Android.bp | 10 +- .../include/AudioPolicyConfig.h | 7 + .../managerdefinitions/include/HwModule.h | 3 +- .../src/AudioPolicyConfig.cpp | 168 +++++++++++++++- .../managerdefinitions/src/HwModule.cpp | 7 + services/audiopolicy/engine/common/Android.bp | 2 +- .../engine/common/include/EngineBase.h | 8 + .../engine/common/src/EngineBase.cpp | 72 ++++--- services/audiopolicy/engine/config/Android.bp | 8 +- .../engine/config/include/EngineConfig.h | 6 +- .../engine/config/src/EngineConfig.cpp | 125 +++++++++++- .../engine/config/tests/Android.bp | 1 + .../engine/interface/EngineInterface.h | 9 + .../audiopolicy/engineconfigurable/Android.bp | 3 +- .../parameter-framework/plugin/Android.bp | 2 +- .../engineconfigurable/src/Engine.cpp | 6 + .../engineconfigurable/src/Engine.h | 11 +- services/audiopolicy/enginedefault/Android.bp | 3 +- .../audiopolicy/enginedefault/src/Engine.cpp | 21 +- .../audiopolicy/enginedefault/src/Engine.h | 9 +- services/audiopolicy/fuzzer/Android.bp | 2 +- .../audiopolicy/managerdefault/Android.bp | 3 +- .../managerdefault/EngineLibrary.cpp | 35 +++- .../managerdefault/EngineLibrary.h | 5 + services/audiopolicy/service/Android.bp | 2 +- .../service/AudioPolicyService.cpp | 21 +- services/audiopolicy/tests/Android.bp | 3 +- 33 files changed, 774 insertions(+), 78 deletions(-) diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp index 3b06245e0b..7262d640a5 100644 --- a/media/audioaidlconversion/AidlConversionCppNdk.cpp +++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -50,6 +52,7 @@ using ::android::String8; 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 +65,7 @@ using media::audio::common::AudioDualMonoMode; 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 +99,26 @@ using media::audio::common::PcmType; //////////////////////////////////////////////////////////////////////////////////////////////////// // Converters +namespace { + +bool isVendorExtension(const std::string& s) { + // Must be the same as defined 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); +} + +std::vector splitString(const std::string& s, char separator) { + std::istringstream iss(s); + std::string t; + std::vector 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; @@ -1799,6 +1823,172 @@ legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) { return unexpected(BAD_VALUE); } +namespace { + +// TODO(b/281850726): Expose publicly once android.media.AudioFlag is removed. +// Until that, `legacy2aidl_audio_flags_mask_t_AudioFlag` function is ambiguous. + +ConversionResult +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 +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 +aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) { + return convertBitmask( + aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_bitmask, + enumToMask_bitmask); +} + +ConversionResult +legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) { + return convertBitmask( + legacy, legacy2aidl_audio_flags_mask_t_AudioFlag, + indexToEnum_bitmask, + enumToMask_bitmask); +} + +} // namespace + +ConversionResult +aidl2legacy_AudioTags_string(const std::vector& aidl) { + std::ostringstream tagsBuffer; + bool hasValue = false; + for (const auto& tag : aidl) { + if (hasValue) { + tagsBuffer << AUDIO_ATTRIBUTES_TAGS_SEPARATOR; + } + if (isVendorExtension(tag)) { + // Note: with the current regex for vendor tags: VX_[A-Z0-9]{3,}_[_A-Z0-9]+ + // it's impossible to create a vendor tag that would contain the separator, but in case + // the criteria changes, we double check it here. + if (strchr(tag.c_str(), AUDIO_ATTRIBUTES_TAGS_SEPARATOR) == nullptr) { + tagsBuffer << tag; + hasValue = true; + } else { + ALOGE("Vendor extension tag is ill-formed: \"%s\"", tag.c_str()); + return unexpected(BAD_VALUE); + } + } + } + return tagsBuffer.str(); +} + +ConversionResult> +legacy2aidl_string_AudioTags(const std::string& legacy) { + auto allTags = splitString(legacy, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); + std::vector result; + std::copy_if(std::make_move_iterator(allTags.begin()), std::make_move_iterator(allTags.end()), + std::back_inserter(result), isVendorExtension); + return result; +} + +ConversionResult +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 +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 aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) { diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h index bc9d4d54bc..fc57f728b3 100644 --- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h +++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h @@ -37,6 +37,7 @@ #define PREFIX(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) @@ -355,6 +357,16 @@ ConversionResult aidl2legacy_AudioUsage_audio_usage_t( ConversionResult legacy2aidl_audio_usage_t_AudioUsage( audio_usage_t legacy); +ConversionResult +aidl2legacy_AudioTags_string(const std::vector& aidl); +ConversionResult> +legacy2aidl_string_AudioTags(const std::string& legacy); + +ConversionResult +aidl2legacy_AudioAttributes_audio_attributes_t(const media::audio::common::AudioAttributes& aidl); +ConversionResult +legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy); + ConversionResult aidl2legacy_AudioUuid_audio_uuid_t( const media::audio::common::AudioUuid &aidl); ConversionResult legacy2aidl_audio_uuid_t_AudioUuid( diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h index f49f681ad3..656d76a62e 100644 --- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h +++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h @@ -118,6 +118,20 @@ ::android::status_t convertRangeWithLimit(InputIterator start, return ::android::OK; } +/** + * A generic template that helps convert containers of convertible types without + * using an intermediate container. + */ +template +::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. */ @@ -208,6 +222,34 @@ using IntegralTypeOf = typename IntegralTypeOfStruct::Type; //////////////////////////////////////////////////////////////////////////////////////////////////// // 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( +// maskField /*int32_t*/, aidl2legacy_AidlEnum_legacy_enum_t /*enumConversion*/, +// indexToEnum_index /*srcIndexToEnum*/, +// enumToMask_bitmask /*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 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 c505e6053b..056698fce9 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 +#include #include namespace { @@ -89,3 +90,42 @@ TEST(AudioRecordTrackMetadata, NonVendorTags) { ASSERT_EQ(1, convBack.value().tags.size()); EXPECT_EQ(initial.tags[1], convBack.value().tags[0]); } + +class AudioTagsRoundTripTest : public testing::TestWithParam> +{ +}; +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::vector{"VX_GOOGLE_41"}, + std::vector{"VX_GOOGLE_41", "VX_GOOGLE_42"})); + +TEST(AudioTags, NonVendorTags) { + const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); + const std::vector initial{ + "random_string", "random" + separator + "string", "VX_GOOGLE_42"}; + auto conv = aidl2legacy_AudioTags_string(initial); + ASSERT_TRUE(conv.ok()); + EXPECT_EQ("VX_GOOGLE_42", conv.value()); +} + +TEST(AudioTags, IllFormedAidlTag) { + const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); + const std::vector initial{"VX_GOOGLE" + separator + "42", "VX_GOOGLE_42"}; + auto conv = aidl2legacy_AudioTags_string(initial); + // Note: with the current regex for vendor tags: VX_[A-Z0-9]{3,}_[_A-Z0-9]+ + // it's impossible to create a vendor tag that would contain the separator, but in case + // the criteria changes, we ensure that either such tags get filtered out or an error happens. + if (conv.ok()) { + EXPECT_EQ("VX_GOOGLE_42", conv.value()); + } else { + EXPECT_FALSE(conv.ok()) << 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 735a14bc6d..206c35b0b0 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 @@ TEST_P(AudioFormatDescriptionRoundTripTest, Ndk2Cpp2Ndk) { 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/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index 3125e31100..308acd0393 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -135,11 +135,8 @@ DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr< } status_t DeviceHalAidl::getAudioPorts(std::vector *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 *routes) { diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp index 1d570b7844..8b76842ba2 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.bp +++ b/services/audiopolicy/common/managerdefinitions/Android.bp @@ -7,9 +7,13 @@ package { 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", @@ -31,7 +35,11 @@ cc_library_static { "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 32c78a1640..1f6002ff70 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -42,6 +43,8 @@ class AudioPolicyConfig : public RefBase // Surround formats, with an optional list of subformats that are equivalent from users' POV. using SurroundFormats = std::unordered_map>; + // 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. @@ -49,6 +52,9 @@ class AudioPolicyConfig : public RefBase // Creates the default (fallback) configuration. static sp createDefault(); + // Attempts to load the configuration from the AIDL config falls back to default on failure. + static sp 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 loadFromApmXmlConfigWithFallback( @@ -140,6 +146,7 @@ class AudioPolicyConfig : public RefBase 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. diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h index 436fcc1364..e994758c7b 100644 --- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h +++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h @@ -39,7 +39,8 @@ typedef Vector > IOProfileCollection; 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 42c76e2298..38e2cc7837 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -26,6 +29,142 @@ namespace android { +using media::audio::common::AudioIoFlags; +using media::audio::common::AudioPortDeviceExt; +using media::audio::common::AudioPortExt; + +namespace { + +ConversionResult> +aidl2legacy_portId_PolicyAudioPort(int32_t portId, + const std::unordered_map>& ports) { + if (auto it = ports.find(portId); it != ports.end()) { + return it->second; + } + return base::unexpected(BAD_VALUE); +} + +ConversionResult> +aidl2legacy_AudioRoute(const media::AudioRoute& aidl, + const std::unordered_map>& ports) { + auto legacy = sp::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 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* legacy, + DeviceVector* attachedInputDevices, DeviceVector* attachedOutputDevices, + sp* defaultOutputDevice) { + *legacy = sp::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> 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::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::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(); + 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 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& aidl, + HwModuleCollection* legacyModules, DeviceVector* attachedInputDevices, + DeviceVector* attachedOutputDevices, sp* defaultOutputDevice) { + for (const auto& aidlModule : aidl) { + sp 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 +aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily& aidl) { + audio_format_t legacyPrimary = VALUE_OR_RETURN( + aidl2legacy_AudioFormatDescription_audio_format_t(aidl.primaryFormat)); + std::unordered_set legacySubs = VALUE_OR_RETURN( + convertContainer>( + aidl.subFormats, aidl2legacy_AudioFormatDescription_audio_format_t)); + return std::make_pair(legacyPrimary, legacySubs); +} + +ConversionResult +aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig& aidl) { + return convertContainer(aidl.formatFamilies, + aidl2legacy_SurroundFormatFamily); +}; + +} // namespace + // static sp AudioPolicyConfig::createDefault() { auto config = sp::make(); @@ -33,6 +172,16 @@ sp AudioPolicyConfig::createDefault() { return config; } +// static +sp AudioPolicyConfig::loadFromApmAidlConfigWithFallback( + const media::AudioPolicyConfig& aidl) { + auto config = sp::make(); + if (status_t status = config->loadFromAidl(aidl); status == NO_ERROR) { + return config; + } + return createDefault(); +} + // static sp AudioPolicyConfig::loadFromApmXmlConfigWithFallback( const std::string& xmlFilePath) { @@ -100,6 +249,22 @@ void AudioPolicyConfig::augmentData() { } } +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)); + // TODO(b/205884982): Remove after landing aosp/2353423. + if (mSurroundFormats.empty()) { + setDefaultSurroundFormats(); + } + 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"); @@ -131,7 +296,8 @@ void AudioPolicyConfig::setDefault() { mOutputDevices.add(mDefaultOutputDevice); mInputDevices.add(defaultInputDevice); - sp module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/); + sp module = new HwModule( + AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_DEVICE_API_VERSION_2_0); mHwModules.add(module); sp outProfile = new OutputProfile("primary"); diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp index 418b7ebe88..5f14ee4623 100644 --- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp @@ -33,6 +33,13 @@ HwModule::HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersi 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/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp index 50c5eab236..6c46c54d41 100644 --- a/services/audiopolicy/engine/common/Android.bp +++ b/services/audiopolicy/engine/common/Android.bp @@ -51,10 +51,10 @@ cc_library_static { "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 bac51f5c8d..b9c94a4fae 100644 --- a/services/audiopolicy/engine/common/include/EngineBase.h +++ b/services/audiopolicy/engine/common/include/EngineBase.h @@ -16,6 +16,9 @@ #pragma once +#include + +#include #include #include #include @@ -113,6 +116,9 @@ class EngineBase : public EngineInterface 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; } @@ -176,6 +182,8 @@ class EngineBase : public EngineInterface const DeviceVector& availableOutputDevices, product_strategy_t strategy) const; private: + engineConfig::ParsingResult processParsingResult(engineConfig::ParsingResult&& rawResult); + /** * Get media devices as the given role * diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp index 7d6a3087c3..218aff80e6 100644 --- a/services/audiopolicy/engine/common/src/EngineBase.cpp +++ b/services/audiopolicy/engine/common/src/EngineBase.cpp @@ -115,10 +115,53 @@ product_strategy_t EngineBase::getProductStrategyByName(const std::string &name) 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(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(config), + static_cast(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(); }), @@ -158,42 +201,21 @@ engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::s }); 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(config), - static_cast(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); diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp index 459cc78b4a..12597de989 100644 --- a/services/audiopolicy/engine/config/Android.bp +++ b/services/audiopolicy/engine/config/Android.bp @@ -22,11 +22,13 @@ cc_library { "-Wextra", ], shared_libs: [ + "libaudio_aidl_conversion_common_cpp", + "libaudiopolicycomponents", + "libcutils", + "liblog", "libmedia_helper", - "libxml2", "libutils", - "liblog", - "libcutils", + "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 4de16c5885..119dbd6694 100644 --- a/services/audiopolicy/engine/config/include/EngineConfig.h +++ b/services/audiopolicy/engine/config/include/EngineConfig.h @@ -16,10 +16,11 @@ #pragma once -#include - #include #include + +#include +#include #include struct _xmlNode; @@ -116,6 +117,7 @@ struct ParsingResult { */ 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 ac117f0efb..ca78ce7213 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 +#include +#include +#include +#include +#include +#include +#include + #define LOG_TAG "APM::AudioPolicyEngine/Config" //#define LOG_NDEBUG 0 #include "EngineConfig.h" +#include +#include #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include namespace android { @@ -45,6 +49,85 @@ static constexpr const char *gVersionAttribute = "version"; static const char *const gReferenceElementName = "reference"; static const char *const gReferenceAttributeName = "name"; +namespace { + +ConversionResult 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( + aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t)); + return legacy; +} + +ConversionResult 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( + aidl.attributesGroups, + aidl2legacy_AudioHalAttributeGroup_AttributesGroup)); + return legacy; +} + +ConversionResult legacy_device_category_to_string(device_category legacy) { + std::string s; + if (DeviceCategoryConverter::toString(legacy, s)) { + return s; + } + return base::unexpected(BAD_VALUE); +} + +ConversionResult 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 aidl2legacy_AudioHalCurvePoint_CurvePoint( + const media::audio::common::AudioHalVolumeCurve::CurvePoint& aidl) { + CurvePoint legacy; + legacy.index = VALUE_OR_RETURN(convertIntegral(aidl.index)); + legacy.attenuationInMb = aidl.attenuationMb; + return legacy; +} + +ConversionResult 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( + aidl.curvePoints, aidl2legacy_AudioHalCurvePoint_CurvePoint)); + return legacy; +} + +ConversionResult 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( + aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve)); + return legacy; +} + +} // namespace + template struct BaseSerializerTraits { typedef E Element; @@ -724,5 +807,25 @@ android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups) { } } +ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) { + auto config = std::make_unique(); + config->version = 1.0f; + if (auto conv = convertContainer( + aidlConfig.productStrategies, + aidl2legacy_AudioHalProductStrategy_ProductStrategy); conv.ok()) { + config->productStrategies = std::move(conv.value()); + } else { + return ParsingResult{}; + } + if (auto conv = convertContainer( + 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 5791f172e0..5d1aa163f9 100644 --- a/services/audiopolicy/engine/config/tests/Android.bp +++ b/services/audiopolicy/engine/config/tests/Android.bp @@ -11,6 +11,7 @@ cc_test { 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 dd7ac1a519..70461ad034 100644 --- a/services/audiopolicy/engine/interface/EngineInterface.h +++ b/services/audiopolicy/engine/interface/EngineInterface.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,14 @@ using CapturePresetDevicesRoleMap = class EngineInterface { 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 diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp index dc8d9cffbe..eb2e2f4ca5 100644 --- a/services/audiopolicy/engineconfigurable/Android.bp +++ b/services/audiopolicy/engineconfigurable/Android.bp @@ -35,14 +35,15 @@ cc_library_shared { "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 0398fc79f2..f7159c5503 100644 --- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp +++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp @@ -31,11 +31,11 @@ cc_library_shared { "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 2eb017797b..ccd431690f 100644 --- a/services/audiopolicy/engineconfigurable/src/Engine.cpp +++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp @@ -70,6 +70,12 @@ Engine::Engine() : mPolicyParameterMgr(new ParameterManagerWrapper()) { } +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); diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h index b964cd66f7..4f3e620c02 100644 --- a/services/audiopolicy/engineconfigurable/src/Engine.h +++ b/services/audiopolicy/engineconfigurable/src/Engine.h @@ -41,12 +41,15 @@ class Engine : public EngineBase, AudioPolicyPluginInterface /// /// 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 @@ class Engine : public EngineBase, AudioPolicyPluginInterface audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const override; - android::status_t setDeviceConnectionState(const sp devDesc, - audio_policy_dev_state_t state) override; + status_t setDeviceConnectionState(const sp devDesc, + audio_policy_dev_state_t state) override; DeviceVector getOutputDevicesForAttributes(const audio_attributes_t &attr, const sp &preferedDevice = nullptr, diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp index 4671fe97c7..7d4ccab0fd 100644 --- a/services/audiopolicy/enginedefault/Android.bp +++ b/services/audiopolicy/enginedefault/Android.bp @@ -25,12 +25,13 @@ cc_library_shared { "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 88cbb7d1f0..15f7842a8b 100644 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -35,10 +35,7 @@ #include #include -namespace android -{ -namespace audio_policy -{ +namespace android::audio_policy { struct legacy_strategy_map { const char *name; legacy_strategy id; }; static const std::vector& getLegacyStrategy() { @@ -59,8 +56,18 @@ static const std::vector& getLegacyStrategy() { 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 +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 @@ status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) { return OK; } + status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) { switch(usage) { @@ -844,5 +852,4 @@ sp Engine::getInputDeviceForAttributes(const audio_attributes_ 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 8410560bec..878bca90b8 100644 --- a/services/audiopolicy/enginedefault/src/Engine.h +++ b/services/audiopolicy/enginedefault/src/Engine.h @@ -47,10 +47,14 @@ class Engine : public EngineBase 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: @@ -79,9 +83,8 @@ class Engine : public EngineBase 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 + 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 621f6430f1..c4b3751794 100644 --- a/services/audiopolicy/fuzzer/Android.bp +++ b/services/audiopolicy/fuzzer/Android.bp @@ -38,6 +38,7 @@ cc_fuzz { "capture_state_listener-aidl-cpp", "libaudioclient", "libaudiofoundation", + "libaudiopolicycomponents", "libbase", "libcutils", "libhidlbase", @@ -54,7 +55,6 @@ cc_fuzz { ], 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 6e34eb06bb..a1785da463 100644 --- a/services/audiopolicy/managerdefault/Android.bp +++ b/services/audiopolicy/managerdefault/Android.bp @@ -23,6 +23,7 @@ cc_library_shared { shared_libs: [ "libaudiofoundation", + "libaudiopolicycomponents", "libcutils", "libdl", "libutils", @@ -49,8 +50,6 @@ cc_library_shared { "libaudiopolicymanager_interface_headers", ], - static_libs: ["libaudiopolicycomponents"], - cflags: [ "-Wall", "-Werror", diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp index 939fbc504d..ab77941cc0 100644 --- a/services/audiopolicy/managerdefault/EngineLibrary.cpp +++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp @@ -40,6 +40,23 @@ EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuf 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::load(const std::string& librarySuffix) { @@ -53,7 +70,8 @@ EngineLibrary::~EngineLibrary() 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 @@ EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlF 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 dc138a1966..4710e34d15 100644 --- a/services/audiopolicy/managerdefault/EngineLibrary.h +++ b/services/audiopolicy/managerdefault/EngineLibrary.h @@ -21,6 +21,7 @@ #include #include +#include namespace android { @@ -28,6 +29,8 @@ using EngineInstance = std::unique_ptr { public: @@ -40,6 +43,8 @@ class EngineLibrary : public std::enable_shared_from_this { 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 2f677da483..f4fc8f1c1e 100644 --- a/services/audiopolicy/service/Android.bp +++ b/services/audiopolicy/service/Android.bp @@ -35,6 +35,7 @@ cc_library_shared { "libaudiofoundation", "libaudiohal", "libaudiopolicy", + "libaudiopolicycomponents", "libaudiopolicymanagerdefault", "libaudiousecasevalidation", "libaudioutils", @@ -66,7 +67,6 @@ cc_library_shared { ], static_libs: [ - "libaudiopolicycomponents", "framework-permission-aidl-cpp", ], diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 936794999b..234104defc 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -186,10 +186,23 @@ static auto& getIAudioPolicyServiceStatistics() { 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/tests/Android.bp b/services/audiopolicy/tests/Android.bp index 285b354e0a..a4a0cd4313 100644 --- a/services/audiopolicy/tests/Android.bp +++ b/services/audiopolicy/tests/Android.bp @@ -78,6 +78,7 @@ cc_test { "libaudioclient", "libaudioclient_aidl_conversion", "libaudiofoundation", + "libaudiopolicycomponents", "libaudiopolicymanagerdefault", "libcutils", "liblog", @@ -89,8 +90,6 @@ cc_test { "libxml2", ], - static_libs: ["libaudiopolicycomponents"], - header_libs: [ "libaudiopolicyengine_interface_headers", "libaudiopolicymanager_interface_headers", From ba5068872ad510562d2dbc280e2d8848ac340192 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Mon, 15 May 2023 13:21:11 -0700 Subject: [PATCH 003/148] Remove temporary workarounds in AIDL HAL config processing Removed the code in DevicesFactoryHalAidl::openDevice which was checking whether the module is actually published. Removed the fallback to default surround sound config when AIDL HAL provided an empty config (this is not allowed). Bug: 205884982 Test: use CF with AIDL audio HAL (cherry picked from https://android-review.googlesource.com/q/commit:0ee6cb9bc347667e8dc30c0a9eedb63420834d86) Merged-In: I1b614e62a28ae1662a3c7fccce62aa943da9431d Change-Id: I1b614e62a28ae1662a3c7fccce62aa943da9431d --- .../impl/DevicesFactoryHalAidl.cpp | 23 ++++++------------- .../src/AudioPolicyConfig.cpp | 4 ---- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp index 8345cd2052..c8cce9698a 100644 --- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp @@ -83,24 +83,15 @@ status_t DevicesFactoryHalAidl::openDevice(const char *name, sp deviceNames; - if (status_t status = getDeviceNames(&deviceNames); status != OK) { - return status; - } std::shared_ptr 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::make(name, service); return OK; } diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp index 38e2cc7837..e214ae9c40 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp @@ -256,10 +256,6 @@ status_t AudioPolicyConfig::loadFromAidl(const media::AudioPolicyConfig& aidl) { media::audio::common::AudioMode::CALL_SCREEN) != aidl.supportedModes.end(); mSurroundFormats = VALUE_OR_RETURN_STATUS( aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig)); - // TODO(b/205884982): Remove after landing aosp/2353423. - if (mSurroundFormats.empty()) { - setDefaultSurroundFormats(); - } mSource = kAidlConfigSource; // No need to augmentData() as AIDL HAL must provide correct mic addresses. return NO_ERROR; From 1c40090c6f42e8a7981999c6de080e3141ed1cd8 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 17 May 2023 11:48:43 -0700 Subject: [PATCH 004/148] Remove AudioAttributesInternal and media.AudioFlag There exist equivalent types from the stable package android.media.audio.common. Switch to these types and remove duplicates. Update aidl<->legacy conversions to allow non-vendor tags within AudioAttributes. Non-vendor tags only get filtered out on the HAL boundary: cpp<->ndk. Bug: 281850726 Test: atest audioclient_serialization_tests Test: atest audio_aidl_ndk_conversion_tests Test: atest audiorouting_tests Test: atest audiosystem_tests Change-Id: If1ff43110c54613c5c29b42a2dc3e5d832708c28 --- .../AidlConversionCppNdk.cpp | 37 +----- .../AidlConversionNdkCpp.cpp | 66 +++++++++- .../include/media/AidlConversionCppNdk-impl.h | 10 ++ .../tests/audio_aidl_ndk_conversion_tests.cpp | 32 +++-- media/libaudioclient/AidlConversion.cpp | 123 ------------------ media/libaudioclient/Android.bp | 2 - media/libaudioclient/AudioSystem.cpp | 66 +++++----- media/libaudioclient/AudioTrack.cpp | 4 +- media/libaudioclient/AudioVolumeGroup.cpp | 6 +- media/libaudioclient/IAudioFlinger.cpp | 8 +- .../libaudioclient/VolumeGroupAttributes.cpp | 4 +- .../aidl/android/media/AudioAttributesEx.aidl | 4 +- .../media/AudioAttributesInternal.aidl | 35 ----- .../aidl/android/media/AudioFlag.aidl | 40 ------ .../aidl/android/media/AudioVolumeGroup.aidl | 4 +- .../android/media/CreateRecordRequest.aidl | 4 +- .../android/media/CreateTrackRequest.aidl | 4 +- .../media/GetOutputForAttrResponse.aidl | 4 +- .../android/media/IAudioPolicyService.aidl | 37 +++--- .../include/media/AidlConversion.h | 17 --- .../tests/audioclient_serialization_tests.cpp | 22 ++-- .../service/AudioPolicyInterfaceImpl.cpp | 82 ++++++------ .../audiopolicy/service/AudioPolicyService.h | 45 ++++--- 23 files changed, 247 insertions(+), 409 deletions(-) delete mode 100644 media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl delete mode 100644 media/libaudioclient/aidl/android/media/AudioFlag.aidl diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp index 7262d640a5..84013e9517 100644 --- a/media/audioaidlconversion/AidlConversionCppNdk.cpp +++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -101,12 +100,6 @@ using media::audio::common::PcmType; namespace { -bool isVendorExtension(const std::string& s) { - // Must be the same as defined 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); -} - std::vector splitString(const std::string& s, char separator) { std::istringstream iss(s); std::string t; @@ -1823,11 +1816,6 @@ legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) { return unexpected(BAD_VALUE); } -namespace { - -// TODO(b/281850726): Expose publicly once android.media.AudioFlag is removed. -// Until that, `legacy2aidl_audio_flags_mask_t_AudioFlag` function is ambiguous. - ConversionResult aidl2legacy_AudioFlag_audio_flags_mask_t(AudioFlag aidl) { switch (aidl) { @@ -1929,8 +1917,6 @@ legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) { enumToMask_bitmask); } -} // namespace - ConversionResult aidl2legacy_AudioTags_string(const std::vector& aidl) { std::ostringstream tagsBuffer; @@ -1939,17 +1925,12 @@ aidl2legacy_AudioTags_string(const std::vector& aidl) { if (hasValue) { tagsBuffer << AUDIO_ATTRIBUTES_TAGS_SEPARATOR; } - if (isVendorExtension(tag)) { - // Note: with the current regex for vendor tags: VX_[A-Z0-9]{3,}_[_A-Z0-9]+ - // it's impossible to create a vendor tag that would contain the separator, but in case - // the criteria changes, we double check it here. - if (strchr(tag.c_str(), AUDIO_ATTRIBUTES_TAGS_SEPARATOR) == nullptr) { - tagsBuffer << tag; - hasValue = true; - } else { - ALOGE("Vendor extension tag is ill-formed: \"%s\"", tag.c_str()); - return unexpected(BAD_VALUE); - } + 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(); @@ -1957,11 +1938,7 @@ aidl2legacy_AudioTags_string(const std::vector& aidl) { ConversionResult> legacy2aidl_string_AudioTags(const std::string& legacy) { - auto allTags = splitString(legacy, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); - std::vector result; - std::copy_if(std::make_move_iterator(allTags.begin()), std::make_move_iterator(allTags.end()), - std::back_inserter(result), isVendorExtension); - return result; + return splitString(legacy, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); } ConversionResult diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp index c64a07445d..ecd2e5ec12 100644 --- a/media/audioaidlconversion/AidlConversionNdkCpp.cpp +++ b/media/audioaidlconversion/AidlConversionNdkCpp.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #define LOG_TAG "AidlConversionNdkCpp" @@ -34,6 +35,24 @@ namespace android { 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& tags) { + if (std::find_if(tags.begin(), tags.end(), isNotVendorExtension) == tags.end()) { + return; + } + std::vector 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 @@ template } // 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,10 +142,46 @@ template } 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 +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/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h index fc57f728b3..7268464dad 100644 --- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h +++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h @@ -357,6 +357,16 @@ ConversionResult aidl2legacy_AudioUsage_audio_usage_t( ConversionResult legacy2aidl_audio_usage_t_AudioUsage( audio_usage_t legacy); +ConversionResult +aidl2legacy_AudioFlag_audio_flags_mask_t(media::audio::common::AudioFlag aidl); +ConversionResult +legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy); + +ConversionResult +aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl); +ConversionResult +legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy); + ConversionResult aidl2legacy_AudioTags_string(const std::vector& aidl); ConversionResult> diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp index 056698fce9..60727b49d8 100644 --- a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp +++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp @@ -107,25 +107,31 @@ INSTANTIATE_TEST_SUITE_P(AudioTagsRoundTrip, AudioTagsRoundTripTest, std::vector{"VX_GOOGLE_41"}, std::vector{"VX_GOOGLE_41", "VX_GOOGLE_42"})); -TEST(AudioTags, NonVendorTags) { +TEST(AudioTags, NonVendorTagsAllowed) { const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR); - const std::vector initial{ - "random_string", "random" + separator + "string", "VX_GOOGLE_42"}; + const std::vector initial{"random_string", "VX_GOOGLE_42"}; auto conv = aidl2legacy_AudioTags_string(initial); ASSERT_TRUE(conv.ok()); - EXPECT_EQ("VX_GOOGLE_42", conv.value()); + 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 initial{"VX_GOOGLE" + separator + "42", "VX_GOOGLE_42"}; - auto conv = aidl2legacy_AudioTags_string(initial); - // Note: with the current regex for vendor tags: VX_[A-Z0-9]{3,}_[_A-Z0-9]+ - // it's impossible to create a vendor tag that would contain the separator, but in case - // the criteria changes, we ensure that either such tags get filtered out or an error happens. - if (conv.ok()) { - EXPECT_EQ("VX_GOOGLE_42", conv.value()); - } else { - EXPECT_FALSE(conv.ok()) << conv.value(); + { + const std::vector 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 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/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp index b32667e3fb..bd10e44db0 100644 --- a/media/libaudioclient/AidlConversion.cpp +++ b/media/libaudioclient/AidlConversion.cpp @@ -480,129 +480,6 @@ ConversionResult legacy2aidl_AudioClient_AudioClient( return aidl; } -ConversionResult -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 -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 -aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) { - return convertBitmask( - aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_index, - enumToMask_bitmask); -} - -ConversionResult -legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) { - return convertBitmask( - legacy, legacy2aidl_audio_flags_mask_t_AudioFlag, - indexToEnum_bitmask, - enumToMask_index); -} - -ConversionResult -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 -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> aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) { sp legacy; diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp index 7122af1afb..01e3d53007 100644 --- a/media/libaudioclient/Android.bp +++ b/media/libaudioclient/Android.bp @@ -281,10 +281,8 @@ aidl_interface { 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", diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 4527e0ff48..7cec2e8879 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -1066,8 +1066,8 @@ status_t AudioSystem::getOutputForAttr(audio_attributes_t* attr, const sp& 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*/)); @@ -1106,7 +1106,7 @@ status_t AudioSystem::getOutputForAttr(audio_attributes_t* attr, *isSpatialized = responseAidl.isSpatialized; *isBitPerfect = responseAidl.isBitPerfect; *attr = VALUE_OR_RETURN_STATUS( - aidl2legacy_AudioAttributesInternal_audio_attributes_t(responseAidl.attr)); + aidl2legacy_AudioAttributes_audio_attributes_t(responseAidl.attr)); return OK; } @@ -1171,8 +1171,8 @@ status_t AudioSystem::getInputForAttr(const audio_attributes_t* attr, const sp& 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)); @@ -1293,8 +1293,8 @@ status_t AudioSystem::setVolumeIndexForAttributes(const audio_attributes_t& attr const sp& 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(index)); AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS( legacy2aidl_audio_devices_t_AudioDeviceDescription(device)); @@ -1308,8 +1308,8 @@ status_t AudioSystem::getVolumeIndexForAttributes(const audio_attributes_t& attr const sp& 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; @@ -1323,8 +1323,8 @@ status_t AudioSystem::getMaxVolumeIndexForAttributes(const audio_attributes_t& a const sp& 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))); @@ -1336,8 +1336,8 @@ status_t AudioSystem::getMinVolumeIndexForAttributes(const audio_attributes_t& a const sp& 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))); @@ -1369,8 +1369,8 @@ status_t AudioSystem::getDevicesForAttributes(const audio_attributes_t& aa, const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - media::AudioAttributesInternal aaAidl = VALUE_OR_RETURN_STATUS( - legacy2aidl_audio_attributes_t_AudioAttributesInternal(aa)); + media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS( + legacy2aidl_audio_attributes_t_AudioAttributes(aa)); std::vector retAidl; RETURN_STATUS_IF_ERROR( statusTFromBinderStatus(aps->getDevicesForAttributes(aaAidl, forVolume, &retAidl))); @@ -1888,8 +1888,8 @@ status_t AudioSystem::startAudioSource(const struct audio_port_config* source, 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))); @@ -2175,8 +2175,8 @@ status_t AudioSystem::getProductStrategyFromAudioAttributes(const audio_attribut const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - media::AudioAttributesInternal aaAidl = VALUE_OR_RETURN_STATUS( - legacy2aidl_audio_attributes_t_AudioAttributesInternal(aa)); + media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS( + legacy2aidl_audio_attributes_t_AudioAttributes(aa)); int32_t productStrategyAidl; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( @@ -2205,8 +2205,8 @@ status_t AudioSystem::getVolumeGroupFromAudioAttributes(const audio_attributes_t const sp& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; - media::AudioAttributesInternal aaAidl = VALUE_OR_RETURN_STATUS( - legacy2aidl_audio_attributes_t_AudioAttributesInternal(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))); @@ -2411,8 +2411,8 @@ status_t AudioSystem::canBeSpatialized(const audio_attributes_t *attr, audio_attributes_t attributes = attr != nullptr ? *attr : AUDIO_ATTRIBUTES_INITIALIZER; audio_config_t configuration = config != nullptr ? *config : AUDIO_CONFIG_INITIALIZER; - std::optional attrAidl = VALUE_OR_RETURN_STATUS( - legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes)); + std::optional attrAidl = VALUE_OR_RETURN_STATUS( + legacy2aidl_audio_attributes_t_AudioAttributes(attributes)); std::optional configAidl = VALUE_OR_RETURN_STATUS( legacy2aidl_audio_config_t_AudioConfig(configuration, false /*isInput*/)); std::vector devicesAidl = VALUE_OR_RETURN_STATUS( @@ -2449,8 +2449,8 @@ status_t AudioSystem::getDirectPlaybackSupport(const audio_attributes_t *attr, 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*/)); @@ -2473,8 +2473,8 @@ status_t AudioSystem::getDirectProfilesForAttributes(const audio_attributes_t* a 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 audioProfilesAidl; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( @@ -2653,8 +2653,8 @@ status_t AudioSystem::setPreferredMixerAttributes(const audio_attributes_t *attr 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)); media::AudioMixerAttributesInternal mixerAttrAidl = VALUE_OR_RETURN_STATUS( legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(*mixerAttr)); int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid)); @@ -2673,8 +2673,8 @@ status_t AudioSystem::getPreferredMixerAttributes( 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 portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId)); std::optional _aidlReturn; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( @@ -2696,8 +2696,8 @@ status_t AudioSystem::clearPreferredMixerAttributes(const audio_attributes_t *at 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 uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid)); int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId)); return statusTFromBinderStatus( diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index f01b6533d9..359c140aca 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -178,8 +178,8 @@ bool AudioTrack::isDirectOutputSupported(const audio_config_base_t& config, auto result = [&]() -> ConversionResult { 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 978599e0e8..c4ca5b9bff 100644 --- a/media/libaudioclient/AudioVolumeGroup.cpp +++ b/media/libaudioclient/AudioVolumeGroup.cpp @@ -49,9 +49,9 @@ legacy2aidl_AudioVolumeGroup(const AudioVolumeGroup& legacy) { aidl.groupId = VALUE_OR_RETURN(legacy2aidl_volume_group_t_int32_t(legacy.getId())); aidl.name = legacy.getName(); aidl.audioAttributes = VALUE_OR_RETURN( - convertContainer>( + convertContainer>( legacy.getAudioAttributes(), - legacy2aidl_audio_attributes_t_AudioAttributesInternal)); + legacy2aidl_audio_attributes_t_AudioAttributes)); aidl.streams = VALUE_OR_RETURN( convertContainer>(legacy.getStreamTypes(), legacy2aidl_audio_stream_type_t_AudioStreamType)); @@ -65,7 +65,7 @@ aidl2legacy_AudioVolumeGroup(const media::AudioVolumeGroup& aidl) { VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)), VALUE_OR_RETURN(convertContainer( aidl.audioAttributes, - aidl2legacy_AudioAttributesInternal_audio_attributes_t)), + aidl2legacy_AudioAttributes_audio_attributes_t)), VALUE_OR_RETURN(convertContainer( aidl.streams, aidl2legacy_AudioStreamType_audio_stream_type_t)) diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp index 7b33a00c02..7caaaaf226 100644 --- a/media/libaudioclient/IAudioFlinger.cpp +++ b/media/libaudioclient/IAudioFlinger.cpp @@ -56,7 +56,7 @@ using media::audio::common::AudioUuid; ConversionResult 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::toA ConversionResult 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*/)); @@ -153,7 +153,7 @@ IAudioFlinger::CreateTrackOutput::fromAidl( ConversionResult 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)); @@ -174,7 +174,7 @@ IAudioFlinger::CreateRecordInput::fromAidl( 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)); diff --git a/media/libaudioclient/VolumeGroupAttributes.cpp b/media/libaudioclient/VolumeGroupAttributes.cpp index 530e73fc4b..938e574fba 100644 --- a/media/libaudioclient/VolumeGroupAttributes.cpp +++ b/media/libaudioclient/VolumeGroupAttributes.cpp @@ -48,7 +48,7 @@ ConversionResult 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())); @@ -60,7 +60,7 @@ aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(const media::AudioAttributes 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 335866f566..7827bdbd2b 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 @@ import android.media.audio.common.AudioStreamType; * {@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 2e7420633d..0000000000 --- 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 acf4e6d9e6..0000000000 --- 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/AudioVolumeGroup.aidl b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl index b95a1d3d33..424f8b8dac 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 @@ parcelable AudioVolumeGroup { /** 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 b938a3eda7..57e8f4219e 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 @@ import android.media.audio.common.AudioConfigBase; * {@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 212221e51c..24e6a6c4a0 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 @@ import android.media.audio.common.AudioConfig; * {@hide} */ parcelable CreateTrackRequest { - AudioAttributesInternal attr; + AudioAttributes attr; AudioConfig config; AudioClient clientInfo; @nullable SharedFileRegion sharedBuffer; diff --git a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl index 9d44bb085e..b814b85cdb 100644 --- a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl +++ b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl @@ -16,9 +16,9 @@ package android.media; +import android.media.audio.common.AudioAttributes; import android.media.audio.common.AudioConfigBase; import android.media.audio.common.AudioStreamType; -import android.media.AudioAttributesInternal; /** * {@hide} */ @@ -38,5 +38,5 @@ parcelable GetOutputForAttrResponse { AudioConfigBase configBase; boolean isBitPerfect; /** The corrected audio attributes. **/ - AudioAttributesInternal attr; + AudioAttributes attr; } diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl index 90ede8bdd6..3e9b27f36c 100644 --- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl +++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl @@ -18,8 +18,6 @@ package android.media; import android.content.AttributionSourceState; -import android.media.AudioAttributesEx; -import android.media.AudioAttributesInternal; import android.media.AudioDirectMode; import android.media.AudioMix; import android.media.AudioMixerAttributesInternal; @@ -43,6 +41,7 @@ import android.media.IAudioPolicyServiceClient; 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; @@ -85,7 +84,7 @@ interface IAudioPolicyService { 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, @@ -98,7 +97,7 @@ interface IAudioPolicyService { 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, @@ -125,20 +124,20 @@ interface IAudioPolicyService { 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 AudioAttributesInternal attr, boolean forVolume); + AudioDevice[] getDevicesForAttributes(in AudioAttributes attr, boolean forVolume); int /* audio_io_handle_t */ getOutputForEffect(in EffectDescriptor desc); @@ -200,7 +199,7 @@ interface IAudioPolicyService { * 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. @@ -272,7 +271,7 @@ interface IAudioPolicyService { 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); @@ -333,10 +332,10 @@ interface IAudioPolicyService { AudioProductStrategy[] listAudioProductStrategies(); int /* product_strategy_t */ getProductStrategyFromAudioAttributes( - in AudioAttributesInternal aa, boolean fallbackOnDefault); + in AudioAttributes aa, boolean fallbackOnDefault); AudioVolumeGroup[] listAudioVolumeGroups(); - int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributesInternal aa, + int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributes aa, boolean fallbackOnDefault); void setRttEnabled(boolean enabled); @@ -397,21 +396,21 @@ interface IAudioPolicyService { * 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); /** * Return a list of AudioMixerAttributes that can be used to set preferred mixer attributes @@ -435,7 +434,7 @@ interface IAudioPolicyService { * playback is routed to the given device. * @param mixerAttr the preferred mixer attributes. */ - void setPreferredMixerAttributes(in AudioAttributesInternal attr, + void setPreferredMixerAttributes(in AudioAttributes attr, int /* audio_port_handle_t */ portId, int /* uid_t */ uid, in AudioMixerAttributesInternal mixerAttr); @@ -449,7 +448,7 @@ interface IAudioPolicyService { * @param portId the port id of the device to be routed. */ @nullable AudioMixerAttributesInternal getPreferredMixerAttributes( - in AudioAttributesInternal attr, + in AudioAttributes attr, int /* audio_port_handle_t */ portId); /** @@ -462,7 +461,7 @@ interface IAudioPolicyService { * preferred mixer attributes. The preferred mixer attributes will only be cleared * if the uid is the same as the owner of current preferred mixer attributes. */ - void clearPreferredMixerAttributes(in AudioAttributesInternal attr, + void clearPreferredMixerAttributes(in AudioAttributes attr, int /* audio_port_handle_t */ portId, int /* uid_t */ uid); diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h index b0d48b7fe6..10f6d4a151 100644 --- a/media/libaudioclient/include/media/AidlConversion.h +++ b/media/libaudioclient/include/media/AidlConversion.h @@ -21,10 +21,8 @@ #include -#include #include #include -#include #include #include #include @@ -105,21 +103,6 @@ ConversionResult aidl2legacy_AudioClient_AudioClient( ConversionResult legacy2aidl_AudioClient_AudioClient( const AudioClient& legacy); -ConversionResult -aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl); -ConversionResult -legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy); - -ConversionResult -aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl); -ConversionResult -legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy); - -ConversionResult -aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl); -ConversionResult -legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy); - ConversionResult> aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl); ConversionResult diff --git a/media/libaudioclient/tests/audioclient_serialization_tests.cpp b/media/libaudioclient/tests/audioclient_serialization_tests.cpp index d1e3d16d4c..707b9b356a 100644 --- a/media/libaudioclient/tests/audioclient_serialization_tests.cpp +++ b/media/libaudioclient/tests/audioclient_serialization_tests.cpp @@ -103,7 +103,7 @@ void FillAudioAttributes::fillAudioAttributes(audio_attributes_t& attr) { attr.usage = kUsages[rand() % kUsages.size()]; attr.source = kInputSources[rand() % kInputSources.size()]; // attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)] - attr.flags = static_cast(rand() & 0x3fff); + attr.flags = static_cast(rand() & 0x3ffd); // exclude AUDIO_FLAG_SECURE sprintf(attr.tags, "%s", CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str()); } @@ -119,6 +119,7 @@ class SerializationTest : public FillAudioAttributes, public ::testing::Test { TEST_F(SerializationTest, AudioProductStrategyBinderization) { for (int j = 0; j < 512; j++) { const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)}; + SCOPED_TRACE(name); std::vector volumeGroupAttrVector; for (auto i = 0; i < 16; i++) { audio_attributes_t attributes; @@ -132,20 +133,19 @@ TEST_F(SerializationTest, AudioProductStrategyBinderization) { 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; + 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()) << name; - for (int i = 0; i < volumeGroupAttrVector.size(); i++) { - EXPECT_EQ(avec[i].getGroupId(), volumeGroupAttrVector[i].getGroupId()) << name; - EXPECT_EQ(avec[i].getStreamType(), volumeGroupAttrVector[i].getStreamType()) << name; - EXPECT_TRUE(avec[i].getAttributes() == volumeGroupAttrVector[i].getAttributes()) - << name; + 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()); } } } diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 2e7b3ffb84..5d86e7cdf1 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -318,7 +318,7 @@ Status AudioPolicyService::getOutput(AudioStreamType streamAidl, int32_t* _aidl_ 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, @@ -327,7 +327,7 @@ Status AudioPolicyService::getOutputForAttr(const media::AudioAttributesInternal 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; @@ -440,7 +440,7 @@ Status AudioPolicyService::getOutputForAttr(const media::AudioAttributesInternal _aidl_return->isSpatialized = isSpatialized; _aidl_return->isBitPerfect = isBitPerfect; _aidl_return->attr = VALUE_OR_RETURN_BINDER_STATUS( - legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr)); + legacy2aidl_audio_attributes_t_AudioAttributes(attr)); } else { _aidl_return->configBase.format = VALUE_OR_RETURN_BINDER_STATUS( legacy2aidl_audio_format_t_AudioFormatDescription(config.format)); @@ -575,7 +575,7 @@ void AudioPolicyService::doReleaseOutput(audio_port_handle_t portId) 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, @@ -585,7 +585,7 @@ Status AudioPolicyService::getInputForAttr(const media::AudioAttributesInternal& 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( @@ -1073,10 +1073,10 @@ Status AudioPolicyService::getStreamVolumeIndex(AudioStreamType streamAidl, } 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(indexAidl)); audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS( aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl)); @@ -1096,10 +1096,10 @@ Status AudioPolicyService::setVolumeIndexForAttributes( } 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; @@ -1118,9 +1118,9 @@ Status AudioPolicyService::getVolumeIndexForAttributes( } 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"))); @@ -1137,9 +1137,9 @@ Status AudioPolicyService::getMinVolumeIndexForAttributes( } 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"))); @@ -1177,12 +1177,13 @@ Status AudioPolicyService::getStrategyForStream(AudioStreamType streamAidl, return Status::ok(); } -Status AudioPolicyService::getDevicesForAttributes(const media::AudioAttributesInternal& attrAidl, - bool forVolume, - std::vector* _aidl_return) +Status AudioPolicyService::getDevicesForAttributes( + const media::audio::common::AudioAttributes& attrAidl, + bool forVolume, + std::vector* _aidl_return) { audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS( - aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl)); + aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl)); AudioDeviceTypeAddrVector devices; if (mAudioPolicyManager == NULL) { @@ -1507,12 +1508,12 @@ Status AudioPolicyService::getOffloadSupport(const AudioOffloadInfo& infoAidl, 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"))); @@ -1829,12 +1830,12 @@ Status AudioPolicyService::removeUserIdDeviceAffinities(int32_t userIdAidl) { } 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))); @@ -2107,10 +2108,10 @@ Status AudioPolicyService::listAudioProductStrategies( } Status AudioPolicyService::getProductStrategyFromAudioAttributes( - const media::AudioAttributesInternal& aaAidl, + const media::audio::common::AudioAttributes& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) { audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS( - aidl2legacy_AudioAttributesInternal_audio_attributes_t(aaAidl)); + aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl)); product_strategy_t productStrategy; if (mAudioPolicyManager == NULL) { @@ -2141,10 +2142,10 @@ Status AudioPolicyService::listAudioVolumeGroups(std::vector& attrAidl, + const std::optional& attrAidl, const std::optional& configAidl, const std::vector& devicesAidl, bool* _aidl_return) { @@ -2391,7 +2392,7 @@ Status AudioPolicyService::canBeSpatialized( 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()) { @@ -2408,9 +2409,10 @@ Status AudioPolicyService::canBeSpatialized( 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); } @@ -2418,7 +2420,7 @@ Status AudioPolicyService::getDirectPlaybackSupport(const media::AudioAttributes 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); @@ -2429,13 +2431,13 @@ Status AudioPolicyService::getDirectPlaybackSupport(const media::AudioAttributes } Status AudioPolicyService::getDirectProfilesForAttributes( - const media::AudioAttributesInternal& attrAidl, + const media::audio::common::AudioAttributes& attrAidl, std::vector* _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); @@ -2470,7 +2472,7 @@ Status AudioPolicyService::getSupportedMixerAttributes( } Status AudioPolicyService::setPreferredMixerAttributes( - const media::AudioAttributesInternal& attrAidl, + const media::audio::common::AudioAttributes& attrAidl, int32_t portIdAidl, int32_t uidAidl, const media::AudioMixerAttributesInternal& mixerAttrAidl) { @@ -2479,7 +2481,7 @@ Status AudioPolicyService::setPreferredMixerAttributes( } audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS( - aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl)); + aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl)); audio_mixer_attributes_t mixerAttr = VALUE_OR_RETURN_BINDER_STATUS( aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(mixerAttrAidl)); uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl)); @@ -2492,7 +2494,7 @@ Status AudioPolicyService::setPreferredMixerAttributes( } Status AudioPolicyService::getPreferredMixerAttributes( - const media::AudioAttributesInternal& attrAidl, + const media::audio::common::AudioAttributes& attrAidl, int32_t portIdAidl, std::optional* _aidl_return) { if (mAudioPolicyManager == nullptr) { @@ -2500,7 +2502,7 @@ Status AudioPolicyService::getPreferredMixerAttributes( } audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS( - aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl)); + aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl)); audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS( aidl2legacy_int32_t_audio_port_handle_t(portIdAidl)); @@ -2515,7 +2517,7 @@ Status AudioPolicyService::getPreferredMixerAttributes( } Status AudioPolicyService::clearPreferredMixerAttributes( - const media::AudioAttributesInternal& attrAidl, + const media::audio::common::AudioAttributes& attrAidl, int32_t portIdAidl, int32_t uidAidl) { if (mAudioPolicyManager == nullptr) { @@ -2523,7 +2525,7 @@ Status AudioPolicyService::clearPreferredMixerAttributes( } audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS( - aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl)); + aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl)); uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl)); audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS( aidl2legacy_int32_t_audio_port_handle_t(portIdAidl)); diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index 4710a8aedd..d0cde6496e 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -98,7 +98,8 @@ class AudioPolicyService : 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, @@ -106,7 +107,7 @@ class AudioPolicyService : 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, @@ -123,19 +124,19 @@ class AudioPolicyService : 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::AudioAttributesInternal& attr, + binder::Status getDevicesForAttributes(const media::audio::common::AudioAttributes& attr, bool forVolume, std::vector* _aidl_return) override; binder::Status getOutputForEffect(const media::EffectDescriptor& desc, @@ -170,7 +171,7 @@ class AudioPolicyService : 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* ports, @@ -201,7 +202,7 @@ class AudioPolicyService : const std::vector& 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; @@ -228,14 +229,16 @@ class AudioPolicyService : binder::Status isHotwordStreamSupported(bool lookbackAudio, bool* _aidl_return) override; binder::Status listAudioProductStrategies( std::vector* _aidl_return) override; - binder::Status getProductStrategyFromAudioAttributes(const media::AudioAttributesInternal& 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* _aidl_return) override; - binder::Status getVolumeGroupFromAudioAttributes(const media::AudioAttributesInternal& 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( @@ -274,31 +277,31 @@ class AudioPolicyService : binder::Status getSpatializer(const sp& callback, media::GetSpatializerResponse* _aidl_return) override; binder::Status canBeSpatialized( - const std::optional& attr, + const std::optional& attr, const std::optional& config, const std::vector& 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* _aidl_return) override; binder::Status getSupportedMixerAttributes( int32_t portId, std::vector* _aidl_return) override; binder::Status setPreferredMixerAttributes( - const media::AudioAttributesInternal& attr, + const media::audio::common::AudioAttributes& attr, int32_t portId, int32_t uid, const media::AudioMixerAttributesInternal& mixerAttr) override; binder::Status getPreferredMixerAttributes( - const media::AudioAttributesInternal& attr, + const media::audio::common::AudioAttributes& attr, int32_t portId, std::optional* _aidl_return) override; - binder::Status clearPreferredMixerAttributes(const media::AudioAttributesInternal& attr, + binder::Status clearPreferredMixerAttributes(const media::audio::common::AudioAttributes& attr, int32_t portId, int32_t uid) override; From c3b60ae2738e3bb3ebc18f2a49ff53f5f4804020 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Mon, 22 May 2023 13:49:46 -0700 Subject: [PATCH 005/148] Add more legacy channel masks for the input direction This is in order to achieve a better parity both with legacy output channel masks and AIDL channel layouts. Bug: 283542128 Test: atest audio_aidl_conversion_tests (cherry picked from https://android-review.googlesource.com/q/commit:4b11bd63941dfbbbae26b9f4f1bb9c39f98cc5fc) Merged-In: I05bc2a5f668eb970c647912ced25a4c87765440e Change-Id: I05bc2a5f668eb970c647912ced25a4c87765440e --- media/audioaidlconversion/AidlConversionCppNdk.cpp | 5 +++++ media/audioaidlconversion/TEST_MAPPING | 1 + .../tests/audio_aidl_legacy_conversion_tests.cpp | 9 +++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp index 84013e9517..4d3f9bd15e 100644 --- a/media/audioaidlconversion/AidlConversionCppNdk.cpp +++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp @@ -279,12 +279,17 @@ const detail::AudioChannelPairs& getInAudioChannelPairs() { 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 }; diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING index 903b88a630..216bc12dab 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/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp index 0d12f9d9e1..976a532133 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 make_ACL_Stereo() { AudioChannelLayout::LAYOUT_STEREO); } +AudioChannelLayout make_ACL_Tri() { + return AudioChannelLayout::make( + AudioChannelLayout::LAYOUT_TRI); +} + AudioChannelLayout make_ACL_LayoutArbitrary() { return AudioChannelLayout::make( // Use channels that exist both for input and output, @@ -311,8 +316,8 @@ INSTANTIATE_TEST_SUITE_P( 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::CHANNEL_FRONT_LEFT), AudioChannelLayout::make( From c15834fc8577c4518eea6683bcf71b46dbeb2442 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 24 May 2023 16:36:26 -0700 Subject: [PATCH 006/148] libaudiohal@aidl: Refactor Android.bp files and reformat tests Refactor definitions in Android.bp to minimize duplicates. Enable clang-format for libaudiohal tests. Bug: 280527932 Test: m (cherry picked from https://android-review.googlesource.com/q/commit:7d717ec0b42fe25a2b740fcc86d7f68683def7f6) Merged-In: I5596f39268c3a67298eb13deda89f072b69b6fbb Change-Id: I5596f39268c3a67298eb13deda89f072b69b6fbb --- PREUPLOAD.cfg | 1 + media/libaudiohal/impl/Android.bp | 59 ++++++++++++++++-------------- media/libaudiohal/tests/Android.bp | 33 ++++------------- 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 1f7083b480..62cf8271f8 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -12,3 +12,4 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp media/libmediatranscoding/ services/mediatranscoding/ media/libaudioclient/tests/ + media/libaudiohal/tests/ diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp index 09e70ebfb8..e52fe67ac6 100644 --- a/media/libaudiohal/impl/Android.bp +++ b/media/libaudiohal/impl/Android.bp @@ -245,16 +245,45 @@ cc_library_shared { ] } -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_core_sounddose_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", @@ -283,30 +312,6 @@ cc_library_shared { "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", - ], } filegroup { diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp index 8210f7d5af..1d4321cdea 100644 --- a/media/libaudiohal/tests/Android.bp +++ b/media/libaudiohal/tests/Android.bp @@ -21,34 +21,24 @@ package { } cc_defaults { - name: "AudioHalTestDefaults", + name: "libaudiohal_aidl_test_default", test_suites: ["device-tests"], defaults: [ - "latest_android_media_audio_common_types_ndk_shared", - ], - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-Wthread-safety", - "-DBACKEND_NDK", + "libaudiohal_default", + "libaudiohal_aidl_default", ], - shared_libs: [ - "audioclient-types-aidl-cpp", - "libaudio_aidl_conversion_common_ndk", "libaudiohal", - "liblog", - "libutils", - "libvibrator", ], } 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 +48,8 @@ cc_test { ":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"], } From 645161f88c5c801595820c708a3b3d1268f03869 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 24 May 2023 16:39:57 -0700 Subject: [PATCH 007/148] libaudiohal@aidl: Process screen state and rotation parameters Translate "screen_state" set parameter into a call to IModule.updateScreenState, and "rotation" into a call to IModule.updateScreenRotation. Bug: 280527932 Test: atest CoreAudioHalAidlTest (cherry picked from https://android-review.googlesource.com/q/commit:626c2985077ae74972f8489e66da245afbeda0a6) Merged-In: I6096d12ac90447bf981f8c405bce19a669cb2ff7 Change-Id: I6096d12ac90447bf981f8c405bce19a669cb2ff7 --- media/libaudiohal/impl/Android.bp | 13 +- media/libaudiohal/tests/Android.bp | 10 + .../tests/CoreAudioHalAidl_test.cpp | 253 ++++++++++++++++++ media/libmediahelper/AudioParameter.cpp | 1 + .../include/media/AudioParameter.h | 2 + 5 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 media/libaudiohal/tests/CoreAudioHalAidl_test.cpp diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp index e52fe67ac6..d63b0abe24 100644 --- a/media/libaudiohal/impl/Android.bp +++ b/media/libaudiohal/impl/Android.bp @@ -285,9 +285,7 @@ cc_library_shared { "libaudiohal_aidl_default", ], srcs: [ - "DeviceHalAidl.cpp", "DevicesFactoryHalEntry.cpp", - "DevicesFactoryHalAidl.cpp", "EffectConversionHelperAidl.cpp", "EffectBufferHalAidl.cpp", "EffectHalAidl.cpp", @@ -309,8 +307,17 @@ cc_library_shared { "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" ], } diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp index 1d4321cdea..8f011c8510 100644 --- a/media/libaudiohal/tests/Android.bp +++ b/media/libaudiohal/tests/Android.bp @@ -32,6 +32,16 @@ cc_defaults { ], } +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"], diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp new file mode 100644 index 0000000000..8433c488c8 --- /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 + +#define LOG_TAG "CoreAudioHalAidlTest" +#include + +#include +#include +#include + +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::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 +struct mf_traits {}; +template +struct mf_traits { + 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 +std::enable_if_t::member_type>, + std::ostream&> +operator<<(std::ostream& os, const P& p) { + return os << p.toString(); +} +template +std::enable_if_t, 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(); + mDevice = sp::make("test", mModule); + } + void TearDown() override { + mDevice.clear(); + mModule.reset(); + } + + protected: + std::shared_ptr mModule; + sp 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/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp index a61a1bc921..3832e90885 100644 --- a/media/libmediahelper/AudioParameter.cpp +++ b/media/libmediahelper/AudioParameter.cpp @@ -33,6 +33,7 @@ const char * const AudioParameter::keyChannels = AUDIO_PARAMETER_STREAM_CHANNELS 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; diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h index 70f8af3259..8568b8fcd1 100644 --- a/media/libmediahelper/include/media/AudioParameter.h +++ b/media/libmediahelper/include/media/AudioParameter.h @@ -41,6 +41,7 @@ class AudioParameter { // 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 @@ class AudioParameter { 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. From d9a58d33c326cc21d63c7d2a268bf679af9d947d Mon Sep 17 00:00:00 2001 From: jiabin Date: Thu, 1 Jun 2023 17:57:30 +0000 Subject: [PATCH 008/148] APM: route all clients to bit-perfect output when it is active. When bit-perfect output is active, all clients should be routed to bit-perfect output so that there won't be issues for the HAL to configure the sink. Bug: 285345410 Test: atest audiopolicy_tests Change-Id: I374171611f02e60f999ac81a0eed4db0c6079313 --- .../managerdefault/AudioPolicyManager.cpp | 21 +++++++++++++------ .../managerdefault/AudioPolicyManager.h | 9 +++++++- .../tests/audiopolicymanager_tests.cpp | 13 ++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index f093e685ba..7d667d5400 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -1293,7 +1293,8 @@ status_t AudioPolicyManager::getOutputForAttrInt( if (outputDevices.size() == 1) { info = getPreferredMixerAttributesInfo( outputDevices.itemAt(0)->getId(), - mEngine->getProductStrategyForAttributes(*resultAttr)); + mEngine->getProductStrategyForAttributes(*resultAttr), + true /*activeBitPerfectPreferred*/); // Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect // and it is currently active. if (info != nullptr && info->getUid() != uid && @@ -4485,16 +4486,24 @@ status_t AudioPolicyManager::setPreferredMixerAttributes( } sp AudioPolicyManager::getPreferredMixerAttributesInfo( - audio_port_handle_t devicePortId, product_strategy_t strategy) { + audio_port_handle_t devicePortId, + product_strategy_t strategy, + bool activeBitPerfectPreferred) { auto it = mPreferredMixerAttrInfos.find(devicePortId); if (it == mPreferredMixerAttrInfos.end()) { return nullptr; } - auto mixerAttrInfoIt = it->second.find(strategy); - if (mixerAttrInfoIt == it->second.end()) { - return nullptr; + if (activeBitPerfectPreferred) { + for (auto [strategy, info] : it->second) { + if ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE + && info->getActiveClientCount() != 0) { + return info; + } + } } - return mixerAttrInfoIt->second; + auto strategyMatchedMixerAttrInfoIt = it->second.find(strategy); + return strategyMatchedMixerAttrInfoIt == it->second.end() + ? nullptr : strategyMatchedMixerAttrInfoIt->second; } status_t AudioPolicyManager::getPreferredMixerAttributes( diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 88bafefdb1..98988e7701 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -1298,8 +1298,15 @@ class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManage uint32_t flags, bool isInput); + /** + * Returns the preferred mixer attributes info for the given device port id and strategy. + * Bit-perfect mixer attributes will be returned if it is active and + * `activeBitPerfectPreferred` is true. + */ sp getPreferredMixerAttributesInfo( - audio_port_handle_t devicePortId, product_strategy_t strategy); + audio_port_handle_t devicePortId, + product_strategy_t strategy, + bool activeBitPerfectPreferred = false); sp reopenOutput( sp outputDesc, diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp index 97a1e0db00..7a21aa88d0 100644 --- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp +++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp @@ -1232,6 +1232,19 @@ TEST_F(AudioPolicyManagerTestWithConfigurationFile, BitPerfectPlayback) { EXPECT_FALSE(isBitPerfect); EXPECT_EQ(bitPerfectOutput, output); + const audio_attributes_t dtmfAttr = { + .content_type = AUDIO_CONTENT_TYPE_UNKNOWN, + .usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING, + }; + audio_io_handle_t dtmfOutput = AUDIO_IO_HANDLE_NONE; + selectedDeviceId = AUDIO_PORT_HANDLE_NONE; + portId = AUDIO_PORT_HANDLE_NONE; + getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, + 48000, AUDIO_OUTPUT_FLAG_NONE, &dtmfOutput, &portId, dtmfAttr, + AUDIO_SESSION_NONE, anotherUid, &isBitPerfect); + EXPECT_FALSE(isBitPerfect); + EXPECT_EQ(bitPerfectOutput, dtmfOutput); + // When configuration matches preferred mixer attributes, which is bit-perfect, but the client // is not the owner of preferred mixer attributes, the playback will not be bit-perfect. getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask, From baab501434a23b599b5b74b76ef173a9a93b84d3 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 31 May 2023 14:24:48 -0700 Subject: [PATCH 009/148] libaudiohal@aidl: Screen state and rotation parameters, p. II aosp/2603929 lacks the actual code for parsing the parameters. This was not discovered because the test was not in TEST_MAPPING. This CL fixes both issues. Bug: 280527932 Test: atest CoreAudioHalAidlTest (cherry picked from https://android-review.googlesource.com/q/commit:e92c34b099b45d5aeab40a45f0877ea7390ac469) Merged-In: Ic42765710f0f1482786b2a0b7feed097206edbeb Change-Id: Ic42765710f0f1482786b2a0b7feed097206edbeb --- media/libaudiohal/TEST_MAPPING | 3 ++ media/libaudiohal/impl/DeviceHalAidl.cpp | 41 ++++++++++++++++++++++++ media/libaudiohal/impl/DeviceHalAidl.h | 1 + 3 files changed, 45 insertions(+) diff --git a/media/libaudiohal/TEST_MAPPING b/media/libaudiohal/TEST_MAPPING index 5d3fb0a013..90f481bb6d 100644 --- a/media/libaudiohal/TEST_MAPPING +++ b/media/libaudiohal/TEST_MAPPING @@ -16,6 +16,9 @@ "include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic_TestAAudioBasic_TestBasic_LOW_LATENCY__OUTPUT" } ] + }, + { + "name": "CoreAudioHalAidlTest" } ] } diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index 308acd0393..a4e1ff69a9 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -286,6 +286,9 @@ status_t DeviceHalAidl::setParameters(const String8& kvPairs) { if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) { ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status); } + if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) { + ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status); + } ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"", __func__, parameters.toString().c_str()); @@ -1253,6 +1256,44 @@ status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter ¶meter return OK; } +status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter ¶meters) { + TIME_CHECK(); + (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter( + parameters, String8(AudioParameter::keyScreenState), + [&](const String8& onOrOff) -> status_t { + std::optional isTurnedOn; + if (onOrOff == AudioParameter::valueOn) { + isTurnedOn = true; + } else if (onOrOff == AudioParameter::valueOff) { + isTurnedOn = false; + } + if (!isTurnedOn.has_value()) { + ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"", + AudioParameter::keyScreenState, onOrOff.c_str()); + return BAD_VALUE; + } + return statusTFromBinderStatus( + mModule->updateScreenState(isTurnedOn.value())); + })); + (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter( + parameters, String8(AudioParameter::keyScreenRotation), + [&](int rotationDegrees) -> status_t { + IModule::ScreenRotation rotation; + switch (rotationDegrees) { + case 0: rotation = IModule::ScreenRotation::DEG_0; break; + case 90: rotation = IModule::ScreenRotation::DEG_90; break; + case 180: rotation = IModule::ScreenRotation::DEG_180; break; + case 270: rotation = IModule::ScreenRotation::DEG_270; break; + default: + ALOGE("setParameters: parameter key \"%s\" has invalid value %d", + AudioParameter::keyScreenRotation, rotationDegrees); + return BAD_VALUE; + } + return statusTFromBinderStatus(mModule->updateScreenRotation(rotation)); + })); + return OK; +} + status_t DeviceHalAidl::findOrCreatePatch( const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) { std::set sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(), diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index 37d800b35e..494bcba206 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -218,6 +218,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, status_t filterAndUpdateBtHfpParameters(AudioParameter ¶meters); status_t filterAndUpdateBtLeParameters(AudioParameter ¶meters); status_t filterAndUpdateBtScoParameters(AudioParameter ¶meters); + status_t filterAndUpdateScreenParameters(AudioParameter ¶meters); status_t findOrCreatePatch( const std::set& sourcePortConfigIds, const std::set& sinkPortConfigIds, From e12539747de611be840a344dca67b249d38780de Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 25 May 2023 17:36:48 -0700 Subject: [PATCH 010/148] System-side vendor extension for handling vendor parameters A mechanism for handling vendor parameters of the Core Audio HAL is introduced. It is realized by means of a system side interface 'IHalAdapterVendorExtension' which can be implemented by the vendor in order to provide bidirectional translation between raw key-value pairs and structured VendorParameter parcelables. If an instance of 'IHalAdapterVendorExtension' is provided (for example, via a system ext partition), the audio framework will use it in order to process parameters that do not map to methods and fields of AOSP Core Audio HAL interfaces, and call 'IModule|IStreamCommon.get|setVendorParameters'. Bug: 274433842 Bug: 278976019 Test: atest CoreAudioHalAidlTest (cherry picked from https://android-review.googlesource.com/q/commit:e7a26adc8d891328fcce5fb14bbc988aa962f128) Merged-In: I8e77238d85cfa91bd7b53e20ad42bd195160fb04 Change-Id: I8e77238d85cfa91bd7b53e20ad42bd195160fb04 --- Android.bp | 24 ++ .../audio/IHalAdapterVendorExtension.aidl | 136 +++++++ media/libaudiohal/impl/Android.bp | 2 + .../libaudiohal/impl/ConversionHelperAidl.cpp | 125 ++++++ media/libaudiohal/impl/ConversionHelperAidl.h | 18 + media/libaudiohal/impl/DeviceHalAidl.cpp | 64 ++- media/libaudiohal/impl/DeviceHalAidl.h | 6 +- .../impl/DevicesFactoryHalAidl.cpp | 19 +- .../libaudiohal/impl/DevicesFactoryHalAidl.h | 6 + media/libaudiohal/impl/StreamHalAidl.cpp | 36 +- media/libaudiohal/impl/StreamHalAidl.h | 13 +- .../tests/CoreAudioHalAidl_test.cpp | 382 +++++++++++++++++- 12 files changed, 783 insertions(+), 48 deletions(-) create mode 100644 aidl/android/media/audio/IHalAdapterVendorExtension.aidl create mode 100644 media/libaudiohal/impl/ConversionHelperAidl.cpp diff --git a/Android.bp b/Android.bp index 37f64575d7..302e250a79 100644 --- a/Android.bp +++ b/Android.bp @@ -102,3 +102,27 @@ cc_library_headers { }, }, } + +aidl_interface { + name: "av-audio-types-aidl", + unstable: true, + host_supported: true, + vendor_available: true, + double_loadable: true, + local_include_dir: "aidl", + srcs: [ + "aidl/android/media/audio/IHalAdapterVendorExtension.aidl", + ], + imports: [ + "android.hardware.audio.core-V1", + ], + backend: { + // The C++ backend is disabled transitively due to use of FMQ by the audio core HAL. + cpp: { + enabled: false, + }, + java: { + sdk_version: "module_current", + }, + }, +} diff --git a/aidl/android/media/audio/IHalAdapterVendorExtension.aidl b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl new file mode 100644 index 0000000000..b7a7678ee8 --- /dev/null +++ b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl @@ -0,0 +1,136 @@ +/* + * 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.audio; + +import android.hardware.audio.core.VendorParameter; + +/** + * This interface is used by the HAL adapter of the Audio Server. Implementation + * is optional. Vendors may provide an implementation on the system_ext + * partition. The default instance of this interface, if provided, must be + * registered prior to the moment when the audio server connects to HAL modules. + * + * {@hide} + */ +interface IHalAdapterVendorExtension { + enum ParameterScope { + MODULE = 0, + STREAM = 1, + } + + /** + * Parse raw parameter keys into vendor parameter ids. + * + * This method prepares arguments for a call to the 'getVendorParameters' + * method of an 'IModule' or an 'IStreamCommon' interface instance, + * depending on the provided scope. + * + * The client calls this method in order to prepare arguments for a call to + * the particular Core HAL interface. The result returned by the HAL is then + * processed using the 'processVendorParameters' method. It is not required + * to maintain a 1:1 correspondence between the provided raw keys and the + * elements of the parsed result. If the returned list is empty, the call of + * 'getVendorParameters' is skipped. The implementation can either ignore + * keys which it does not recognize, or throw an error. The latter is + * preferred as it can help in discovering malformed key names. + * + * @param scope The scope of all raw parameter keys. + * @param rawKeys Raw parameter keys, joined into a string using a semicolon + * (';') as the delimiter. + * @return A list of vendor parameter IDs, see android.hardware.audio.core.VendorParameter. + * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw keys + * and prefers to signal an error. + */ + @utf8InCpp String[] parseVendorParameterIds( + ParameterScope scope, in @utf8InCpp String rawKeys); + + /** + * Parse raw parameter key-value pairs into vendor parameters. + * + * This method prepares arguments for a call to the 'setVendorParameters' + * method of an 'IModule' or an 'IStreamCommon' interface instance, + * depending on the provided scope. + * + * The vendor parameters returned using 'syncParameters' argument is then + * used to call the 'setVendorParameters' method with 'async = false', and + * 'asyncParameters' is used in a subsequent call to the same method, but + * with 'async = true'. It is not required to maintain a 1:1 correspondence + * between the provided key-value pairs and the elements of parsed + * results. If any of the returned lists of vendor parameters is empty, then + * the corresponding call is skipped. The implementation can either ignore + * keys which it does not recognize, and invalid values, or throw an + * error. The latter is preferred as it can help in discovering malformed + * key names and values. + * + * @param scope The scope of all raw key-value pairs. + * @param rawKeys Raw key-value pairs, separated by the "equals" sign ('='), + * joined into a string using a semicolon (';') as the delimiter. + * @param syncParameters A list of vendor parameters to be set synchronously. + * @param asyncParameters A list of vendor parameters to be set asynchronously. + * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse raw key-value + * pairs and prefers to signal an error. + */ + void parseVendorParameters( + ParameterScope scope, in @utf8InCpp String rawKeysAndValues, + out VendorParameter[] syncParameters, out VendorParameter[] asyncParameters); + + /** + * Parse raw value of the parameter for BT A2DP reconfiguration. + * + * This method may return any number of vendor parameters (including zero) + * which will be passed to the 'IBluetoothA2dp.reconfigureOffload' method. + * + * @param rawValue An unparsed value of the legacy parameter. + * @return A list of vendor parameters. + * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value. + */ + VendorParameter[] parseBluetoothA2dpReconfigureOffload(in @utf8InCpp String rawValue); + + /** + * Parse raw value of the parameter for BT LE reconfiguration. + * + * This method may return any number of vendor parameters (including zero) + * which will be passed to the 'IBluetoothLe.reconfigureOffload' method. + * + * @param rawValue An unparsed value of the legacy parameter. + * @return A list of vendor parameters. + * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value. + */ + VendorParameter[] parseBluetoothLeReconfigureOffload(in @utf8InCpp String rawValue); + + /** + * Process vendor parameters returned by the Audio Core HAL. + * + * This processes the result returned from a call to the + * 'getVendorParameters' method of an 'IModule' or an 'IStreamCommon' + * interface instance, depending on the provided scope. + * + * See 'parseVendorParameterIds' method for the flow description. It is not + * required to maintain a 1:1 correspondence between the elements of the + * provided list and the emitted key-value pairs. The returned string with + * raw key-value pairs is passed back to the framework. + * + * @param scope The scope of vendor parameters. + * @param parameters Vendor parameters, see android.hardware.audio.core.VendorParameter. + * @return Key-value pairs, separated by the "equals" sign ('='), + * joined into a string using a semicolon (';') as the delimiter. + * @throws EX_ILLEGAL_ARGUMENT If the implementation can not emit raw key-value + * pairs and prefers to signal an error. + */ + @utf8InCpp String processVendorParameters( + ParameterScope scope, in VendorParameter[] parameters); +} diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp index d63b0abe24..16893655f0 100644 --- a/media/libaudiohal/impl/Android.bp +++ b/media/libaudiohal/impl/Android.bp @@ -257,6 +257,7 @@ cc_defaults { shared_libs: [ "android.hardware.common-V2-ndk", "android.hardware.common.fmq-V1-ndk", + "av-audio-types-aidl-ndk", "libaudio_aidl_conversion_common_cpp", "libaudio_aidl_conversion_common_ndk", "libaudio_aidl_conversion_common_ndk_cpp", @@ -315,6 +316,7 @@ cc_library_shared { filegroup { name: "core_audio_hal_aidl_src_files", srcs: [ + "ConversionHelperAidl.cpp", "DeviceHalAidl.cpp", "DevicesFactoryHalAidl.cpp", "StreamHalAidl.cpp", diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp new file mode 100644 index 0000000000..7197bf2a27 --- /dev/null +++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp @@ -0,0 +1,125 @@ +/* + * 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_TAG "ConversionHelperAidl" + +#include + +#include +#include + +#include "ConversionHelperAidl.h" + +using aidl::android::aidl_utils::statusTFromBinderStatus; +using aidl::android::hardware::audio::core::VendorParameter; +using aidl::android::media::audio::IHalAdapterVendorExtension; + +namespace android { + +status_t parseAndGetVendorParameters( + std::shared_ptr vendorExt, + const VendorParametersRecipient& recipient, + const AudioParameter& parameterKeys, + String8* values) { + using ParameterScope = IHalAdapterVendorExtension::ParameterScope; + if (parameterKeys.size() == 0) return OK; + const String8 rawKeys = parameterKeys.keysToString(); + if (vendorExt == nullptr) { + ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str()); + return OK; + } + + std::vector parameterIds; + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds( + ParameterScope(recipient.index()), + std::string(rawKeys.c_str()), ¶meterIds))); + if (parameterIds.empty()) return OK; + + std::vector parameters; + if (recipient.index() == static_cast(ParameterScope::MODULE)) { + auto module = std::get(ParameterScope::MODULE)>(recipient); + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters( + parameterIds, ¶meters))); + } else if (recipient.index() == static_cast(ParameterScope::STREAM)) { + auto stream = std::get(ParameterScope::STREAM)>(recipient); + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->getVendorParameters( + parameterIds, ¶meters))); + } else { + LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu", + __func__, recipient.index()); + } + if (!parameters.empty()) { + std::string vendorParameters; + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->processVendorParameters( + ParameterScope(recipient.index()), + parameters, &vendorParameters))); + // Re-parse the vendor-provided string to ensure that it is correct. + AudioParameter reparse(String8(vendorParameters.c_str())); + if (reparse.size() != 0) { + if (!values->empty()) { + values->append(";"); + } + values->append(reparse.toString().c_str()); + } + } + return OK; +} + +status_t parseAndSetVendorParameters( + std::shared_ptr vendorExt, + const VendorParametersRecipient& recipient, + const AudioParameter& parameters) { + using ParameterScope = IHalAdapterVendorExtension::ParameterScope; + if (parameters.size() == 0) return OK; + const String8 rawKeysAndValues = parameters.toString(); + if (vendorExt == nullptr) { + ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str()); + return OK; + } + + std::vector syncParameters, asyncParameters; + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters( + ParameterScope(recipient.index()), + std::string(rawKeysAndValues.c_str()), + &syncParameters, &asyncParameters))); + if (recipient.index() == static_cast(ParameterScope::MODULE)) { + auto module = std::get(ParameterScope::MODULE)>(recipient); + if (!syncParameters.empty()) { + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters( + syncParameters, false /*async*/))); + } + if (!asyncParameters.empty()) { + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters( + asyncParameters, true /*async*/))); + } + } else if (recipient.index() == static_cast(ParameterScope::STREAM)) { + auto stream = std::get(ParameterScope::STREAM)>(recipient); + if (!syncParameters.empty()) { + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters( + syncParameters, false /*async*/))); + } + if (!asyncParameters.empty()) { + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters( + asyncParameters, true /*async*/))); + } + } else { + LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu", + __func__, recipient.index()); + } + return OK; +} + +} // namespace android diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h index 5534d13524..0fadd9c9d1 100644 --- a/media/libaudiohal/impl/ConversionHelperAidl.h +++ b/media/libaudiohal/impl/ConversionHelperAidl.h @@ -18,8 +18,12 @@ #include #include +#include #include +#include +#include +#include #include #include #include @@ -74,4 +78,18 @@ error::Result filterOutAndProcessParameter( return false; } +// Must use the same order of elements as IHalAdapterVendorExtension::ParameterScope. +using VendorParametersRecipient = std::variant< + std::shared_ptr<::aidl::android::hardware::audio::core::IModule>, + std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>>; +status_t parseAndGetVendorParameters( + std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt, + const VendorParametersRecipient& recipient, + const AudioParameter& parameterKeys, + String8* values); +status_t parseAndSetVendorParameters( + std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt, + const VendorParametersRecipient& recipient, + const AudioParameter& parameters); + } // namespace android diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index a4e1ff69a9..b1b7e00db6 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -62,6 +62,7 @@ using aidl::android::media::audio::common::Float; using aidl::android::media::audio::common::Int; using aidl::android::media::audio::common::MicrophoneDynamicInfo; using aidl::android::media::audio::common::MicrophoneInfo; +using aidl::android::media::audio::IHalAdapterVendorExtension; using aidl::android::hardware::audio::common::getFrameSizeInBytes; using aidl::android::hardware::audio::common::isBitPositionFlagSet; using aidl::android::hardware::audio::common::isDefaultAudioFormat; @@ -76,6 +77,7 @@ using aidl::android::hardware::audio::core::IModule; using aidl::android::hardware::audio::core::ITelephony; using aidl::android::hardware::audio::core::ModuleDebug; using aidl::android::hardware::audio::core::StreamDescriptor; +using aidl::android::hardware::audio::core::VendorParameter; namespace android { @@ -125,9 +127,10 @@ std::shared_ptr retrieveSubInterface(const std::shared_ptr& module, } // namespace -DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr& module) +DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr& module, + const std::shared_ptr& vext) : ConversionHelperAidl("DeviceHalAidl"), - mInstance(instance), mModule(module), + mInstance(instance), mModule(module), mVendorExt(vext), mTelephony(retrieveSubInterface(module, &IModule::getTelephony)), mBluetooth(retrieveSubInterface(module, &IModule::getBluetooth)), mBluetoothA2dp(retrieveSubInterface(module, &IModule::getBluetoothA2dp)), @@ -289,19 +292,21 @@ status_t DeviceHalAidl::setParameters(const String8& kvPairs) { if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) { ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status); } - - ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"", - __func__, parameters.toString().c_str()); - return OK; + return parseAndSetVendorParameters(mVendorExt, mModule, parameters); } -status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) { +status_t DeviceHalAidl::getParameters(const String8& keys, 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__); - return OK; + if (values == nullptr) { + return BAD_VALUE; + } + AudioParameter parameterKeys(keys), result; + if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) { + ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status); + } + *values = result.toString(); + return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values); } namespace { @@ -571,7 +576,7 @@ status_t DeviceHalAidl::openOutputStream( return NO_INIT; } *outStream = sp::make(*config, std::move(context), aidlPatch.latenciesMs[0], - std::move(ret.stream), this /*callbackBroker*/); + std::move(ret.stream), mVendorExt, this /*callbackBroker*/); mStreams.insert(std::pair(*outStream, aidlPatch.id)); void* cbCookie = (*outStream).get(); { @@ -632,7 +637,7 @@ status_t DeviceHalAidl::openInputStream( return NO_INIT; } *inStream = sp::make(*config, std::move(context), aidlPatch.latenciesMs[0], - std::move(ret.stream), this /*micInfoProvider*/); + std::move(ret.stream), mVendorExt, this /*micInfoProvider*/); mStreams.insert(std::pair(*inStream, aidlPatch.id)); cleanups.disarmAll(); return OK; @@ -1112,9 +1117,23 @@ status_t DeviceHalAidl::createOrUpdatePortConfig( return OK; } +status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters( + AudioParameter &keys, AudioParameter *result) { + TIME_CHECK(); + if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) { + keys.remove(key); + bool supports; + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( + mBluetoothA2dp->supportsOffloadReconfiguration(&supports))); + result->addInt(key, supports ? 1 : 0); + } + return OK; +} + status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶meters) { TIME_CHECK(); std::optional a2dpEnabled; + std::optional> reconfigureOffload; (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter( parameters, String8(AudioParameter::keyBtA2dpSuspended), [&a2dpEnabled](const String8& trueOrFalse) { @@ -1129,10 +1148,27 @@ status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter ¶mete AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str()); return BAD_VALUE; })); - // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin + (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter( + parameters, String8(AudioParameter::keyReconfigA2dp), + [&](const String8& value) -> status_t { + if (mVendorExt != nullptr) { + std::vector result; + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( + mVendorExt->parseBluetoothA2dpReconfigureOffload( + std::string(value.c_str()), &result))); + reconfigureOffload = std::move(result); + } else { + reconfigureOffload = std::vector(); + } + return OK; + })); if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) { return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value())); } + if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) { + return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload( + reconfigureOffload.value())); + } return OK; } diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index 494bcba206..03afbb7238 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -203,7 +204,8 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, // Must not be constructed directly by clients. DeviceHalAidl( const std::string& instance, - const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module); + const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module, + const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext); ~DeviceHalAidl() override = default; @@ -214,6 +216,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, status_t createOrUpdatePortConfig( const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result, bool *created); + status_t filterAndRetrieveBtA2dpParameters(AudioParameter &keys, AudioParameter *result); status_t filterAndUpdateBtA2dpParameters(AudioParameter ¶meters); status_t filterAndUpdateBtHfpParameters(AudioParameter ¶meters); status_t filterAndUpdateBtLeParameters(AudioParameter ¶meters); @@ -292,6 +295,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, const std::string mInstance; const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule; + const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt; 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; diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp index c8cce9698a..f00b1a06b7 100644 --- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp @@ -34,7 +34,8 @@ using aidl::android::hardware::audio::core::IConfig; using aidl::android::hardware::audio::core::IModule; using aidl::android::hardware::audio::core::SurroundSoundConfig; using aidl::android::media::audio::common::AudioHalEngineConfig; -using ::android::detail::AudioHalVersionInfo; +using aidl::android::media::audio::IHalAdapterVendorExtension; +using android::detail::AudioHalVersionInfo; namespace android { @@ -92,7 +93,7 @@ status_t DevicesFactoryHalAidl::openDevice(const char *name, sp::make(name, service); + *device = sp::make(name, service, getVendorExtension()); return OK; } @@ -154,6 +155,20 @@ status_t DevicesFactoryHalAidl::getEngineConfig( return OK; } +std::shared_ptr DevicesFactoryHalAidl::getVendorExtension() { + if (!mVendorExt.has_value()) { + auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default"; + if (AServiceManager_isDeclared(serviceName.c_str())) { + mVendorExt = std::shared_ptr( + IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder( + AServiceManager_waitForService(serviceName.c_str())))); + } else { + mVendorExt = nullptr; + } + } + return mVendorExt.value(); +} + // Main entry-point to the shared library. extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() { auto serviceName = std::string(IConfig::descriptor) + "/default"; diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h index 21957bc85e..97e3796d4f 100644 --- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h +++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include @@ -46,6 +47,11 @@ class DevicesFactoryHalAidl : public DevicesFactoryHalInterface private: const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig; + std::optional> + mVendorExt; + + std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension(); + ~DevicesFactoryHalAidl() = default; }; diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp index d1044dca3e..c84f80ff15 100644 --- a/media/libaudiohal/impl/StreamHalAidl.cpp +++ b/media/libaudiohal/impl/StreamHalAidl.cpp @@ -43,6 +43,7 @@ using ::aidl::android::hardware::audio::core::IStreamOut; using ::aidl::android::hardware::audio::core::StreamDescriptor; using ::aidl::android::hardware::audio::core::MmapBufferDescriptor; using ::aidl::android::media::audio::common::MicrophoneDynamicInfo; +using ::aidl::android::media::audio::IHalAdapterVendorExtension; namespace android { @@ -73,12 +74,14 @@ std::shared_ptr StreamHalAidl::getStreamCommon(const std::shared_ StreamHalAidl::StreamHalAidl( std::string_view className, bool isInput, const audio_config& config, int32_t nominalLatency, StreamContextAidl&& context, - const std::shared_ptr& stream) + const std::shared_ptr& stream, + const std::shared_ptr& vext) : ConversionHelperAidl(className), mIsInput(isInput), mConfig(configToBase(config)), mContext(std::move(context)), - mStream(stream) { + mStream(stream), + mVendorExt(vext) { { std::lock_guard l(mLock); mLastReply.latencyMs = nominalLatency; @@ -125,7 +128,6 @@ status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) { status_t StreamHalAidl::setParameters(const String8& kvPairs) { TIME_CHECK(); if (!mStream) return NO_INIT; - AudioParameter parameters(kvPairs); ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str()); @@ -134,18 +136,18 @@ status_t StreamHalAidl::setParameters(const String8& kvPairs) { [&](int hwAvSyncId) { return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId)); })); - - ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s", - __func__, parameters.toString().c_str()); - return OK; + return parseAndSetVendorParameters(mVendorExt, mStream, parameters); } status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) { - ALOGD("%p %s::%s", this, getClassName().c_str(), __func__); TIME_CHECK(); - values->clear(); - // AIDL HAL doesn't support getParameters API. - return INVALID_OPERATION; + if (!mStream) return NO_INIT; + if (values == nullptr) { + return BAD_VALUE; + } + AudioParameter parameterKeys(keys), result; + *values = result.toString(); + return parseAndGetVendorParameters(mVendorExt, mStream, parameterKeys, values); } status_t StreamHalAidl::getFrameSize(size_t *size) { @@ -533,9 +535,11 @@ StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::Source StreamOutHalAidl::StreamOutHalAidl( const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency, - const std::shared_ptr& stream, const sp& callbackBroker) + const std::shared_ptr& stream, + const std::shared_ptr& vext, + const sp& callbackBroker) : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency, - std::move(context), getStreamCommon(stream)), + std::move(context), getStreamCommon(stream), vext), mStream(stream), mCallbackBroker(callbackBroker) { // Initialize the offload metadata mOffloadMetadata.sampleRate = static_cast(config.sample_rate); @@ -861,9 +865,11 @@ StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetada StreamInHalAidl::StreamInHalAidl( const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency, - const std::shared_ptr& stream, const sp& micInfoProvider) + const std::shared_ptr& stream, + const std::shared_ptr& vext, + const sp& micInfoProvider) : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency, - std::move(context), getStreamCommon(stream)), + std::move(context), getStreamCommon(stream), vext), mStream(stream), mMicInfoProvider(micInfoProvider) {} status_t StreamInHalAidl::setGain(float gain) { diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h index 75a1dd98c8..3b369bd999 100644 --- a/media/libaudiohal/impl/StreamHalAidl.h +++ b/media/libaudiohal/impl/StreamHalAidl.h @@ -26,9 +26,11 @@ #include #include #include +#include #include #include #include +#include #include #include "ConversionHelperAidl.h" @@ -48,7 +50,7 @@ class StreamContextAidl { typedef AidlMessageQueue DataMQ; - explicit StreamContextAidl( + StreamContextAidl( ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor, bool isAsynchronous) : mFrameSizeBytes(descriptor.frameSizeBytes), @@ -185,6 +187,9 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper status_t legacyReleaseAudioPatch() override; protected: + // For tests. + friend class sp; + template static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon( const std::shared_ptr& stream); @@ -195,7 +200,8 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper const audio_config& config, int32_t nominalLatency, StreamContextAidl&& context, - const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream); + const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream, + const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext); ~StreamHalAidl() override; @@ -247,6 +253,7 @@ class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelper ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr); const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream; + const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt; std::mutex mLock; ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock); // mStreamPowerLog is used for audio signal power logging. @@ -349,6 +356,7 @@ class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl { StreamOutHalAidl( const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency, const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream, + const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext, const sp& callbackBroker); ~StreamOutHalAidl() override; @@ -401,6 +409,7 @@ class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl { StreamInHalAidl( const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency, const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream, + const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext, const sp& micInfoProvider); ~StreamInHalAidl() override = default; diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp index 8433c488c8..ea20794cd4 100644 --- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp +++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp @@ -15,17 +15,56 @@ */ #include +#include +#include #define LOG_TAG "CoreAudioHalAidlTest" #include #include +#include #include +#include +#include +#include #include namespace { -class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule { +using ::aidl::android::hardware::audio::core::VendorParameter; + +class VendorParameterMock { + public: + const std::vector& getRetrievedParameterIds() const { return mGetParameterIds; } + const std::vector& getAsyncParameters() const { return mAsyncParameters; } + const std::vector& getSyncParameters() const { return mSyncParameters; } + + protected: + ndk::ScopedAStatus getVendorParametersImpl(const std::vector& in_parameterIds) { + mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(), + in_parameterIds.end()); + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus setVendorParametersImpl(const std::vector& in_parameters, + bool async) { + if (async) { + mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(), + in_parameters.end()); + } else { + mSyncParameters.insert(mSyncParameters.end(), in_parameters.begin(), + in_parameters.end()); + } + return ndk::ScopedAStatus::ok(); + } + + private: + std::vector mGetParameterIds; + std::vector mAsyncParameters; + std::vector mSyncParameters; +}; + +class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule, + public VendorParameterMock { public: bool isScreenTurnedOn() const { return mIsScreenTurnedOn; } ScreenRotation getScreenRotation() const { return mScreenRotation; } @@ -132,15 +171,13 @@ class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus getVendorParameters( - const std::vector&, - std::vector<::aidl::android::hardware::audio::core::VendorParameter>*) override { - return ndk::ScopedAStatus::ok(); + ndk::ScopedAStatus getVendorParameters(const std::vector& in_parameterIds, + std::vector*) override { + return getVendorParametersImpl(in_parameterIds); } - ndk::ScopedAStatus setVendorParameters( - const std::vector<::aidl::android::hardware::audio::core::VendorParameter>&, - bool) override { - return ndk::ScopedAStatus::ok(); + ndk::ScopedAStatus setVendorParameters(const std::vector& in_parameters, + bool async) override { + return setVendorParametersImpl(in_parameters, async); } ndk::ScopedAStatus addDeviceEffect( int32_t, @@ -169,15 +206,166 @@ class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule { ScreenRotation mScreenRotation = ScreenRotation::DEG_0; }; -android::String8 createParameterString(const char* key, const char* value) { +class StreamCommonMock : public ::aidl::android::hardware::audio::core::BnStreamCommon, + public VendorParameterMock { + ndk::ScopedAStatus close() override { return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus prepareToClose() override { return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus updateHwAvSyncId(int32_t) override { return ndk::ScopedAStatus::ok(); } + ndk::ScopedAStatus getVendorParameters(const std::vector& in_parameterIds, + std::vector*) override { + return getVendorParametersImpl(in_parameterIds); + } + ndk::ScopedAStatus setVendorParameters(const std::vector& in_parameters, + bool async) override { + return setVendorParametersImpl(in_parameters, async); + } + ndk::ScopedAStatus addEffect( + const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override { + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus removeEffect( + const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override { + return ndk::ScopedAStatus::ok(); + } +}; + +VendorParameter makeVendorParameter(const std::string& id, int value) { + VendorParameter result{.id = id}; + // Note: in real life, a parcelable type defined by vendor must be used, + // here we use Int just for test purposes. + ::aidl::android::media::audio::common::Int vendorValue{.value = value}; + result.ext.setParcelable(std::move(vendorValue)); + return result; +} + +android::status_t parseVendorParameter(const VendorParameter& param, int* value) { + std::optional<::aidl::android::media::audio::common::Int> vendorValue; + RETURN_STATUS_IF_ERROR(param.ext.getParcelable(&vendorValue)); + if (!vendorValue.has_value()) return android::BAD_VALUE; + *value = vendorValue.value().value; + return android::OK; +} + +class TestHalAdapterVendorExtension + : public ::aidl::android::media::audio::BnHalAdapterVendorExtension { + public: + static const std::string kLegacyParameterKey; + static const std::string kLegacyAsyncParameterKey; + static const std::string kModuleVendorParameterId; + static const std::string kStreamVendorParameterId; + + private: + ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope, + const std::string& in_rawKeys, + std::vector* _aidl_return) override { + android::AudioParameter keys(android::String8(in_rawKeys.c_str())); + for (size_t i = 0; i < keys.size(); ++i) { + android::String8 key; + if (android::status_t status = keys.getAt(i, key); status != android::OK) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + switch (in_scope) { + case ParameterScope::MODULE: + if (key == android::String8(kLegacyParameterKey.c_str()) || + key == android::String8(kLegacyAsyncParameterKey.c_str())) { + _aidl_return->push_back(kModuleVendorParameterId); + } else { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + break; + case ParameterScope::STREAM: + if (key == android::String8(kLegacyParameterKey.c_str()) || + key == android::String8(kLegacyAsyncParameterKey.c_str())) { + _aidl_return->push_back(kStreamVendorParameterId); + } else { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + break; + } + } + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus parseVendorParameters( + ParameterScope in_scope, const std::string& in_rawKeysAndValues, + std::vector* out_syncParameters, + std::vector* out_asyncParameters) override { + android::AudioParameter legacy(android::String8(in_rawKeysAndValues.c_str())); + for (size_t i = 0; i < legacy.size(); ++i) { + android::String8 key; + if (android::status_t status = legacy.getAt(i, key); status != android::OK) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + int value; + if (android::status_t status = legacy.getInt(key, value); status != android::OK) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + std::string parameterId; + switch (in_scope) { + case ParameterScope::MODULE: + parameterId = kModuleVendorParameterId; + break; + case ParameterScope::STREAM: + parameterId = kStreamVendorParameterId; + break; + } + if (key == android::String8(kLegacyParameterKey.c_str())) { + out_syncParameters->push_back(makeVendorParameter(parameterId, value)); + } else if (key == android::String8(kLegacyAsyncParameterKey.c_str())) { + out_asyncParameters->push_back(makeVendorParameter(parameterId, value)); + } else { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + } + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload( + const std::string&, std::vector*) override { + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&, + std::vector*) override { + return ndk::ScopedAStatus::ok(); + } + ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope, + const std::vector& in_parameters, + std::string* _aidl_return) override { + android::AudioParameter legacy; + for (const auto& vendorParam : in_parameters) { + if ((in_scope == ParameterScope::MODULE && + vendorParam.id == kModuleVendorParameterId) || + (in_scope == ParameterScope::STREAM && + vendorParam.id == kStreamVendorParameterId)) { + int value; + if (android::status_t status = parseVendorParameter(vendorParam, &value); + status != android::OK) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + legacy.addInt(android::String8(kLegacyParameterKey.c_str()), value); + } + } + *_aidl_return = legacy.toString().c_str(); + return ndk::ScopedAStatus::ok(); + } +}; + +const std::string TestHalAdapterVendorExtension::kLegacyParameterKey = "aosp_test_param"; +const std::string TestHalAdapterVendorExtension::kLegacyAsyncParameterKey = "aosp_test_param_async"; +// Note: in real life, there is no need to explicitly separate "module" and "stream" +// parameters, here it's done just for test purposes. +const std::string TestHalAdapterVendorExtension::kModuleVendorParameterId = + "aosp.test.module.parameter"; +const std::string TestHalAdapterVendorExtension::kStreamVendorParameterId = + "aosp.test.stream.parameter"; + +android::String8 createParameterString(const std::string& key, const std::string& value) { android::AudioParameter params; - params.add(android::String8(key), android::String8(value)); + params.add(android::String8(key.c_str()), android::String8(value.c_str())); return params.toString(); } -android::String8 createParameterString(const char* key, int value) { +android::String8 createParameterString(const std::string& key, int value) { android::AudioParameter params; - params.addInt(android::String8(key), value); + params.addInt(android::String8(key.c_str()), value); return params.toString(); } @@ -211,7 +399,7 @@ class DeviceHalAidlTest : public testing::Test { public: void SetUp() override { mModule = ndk::SharedRefBase::make(); - mDevice = sp::make("test", mModule); + mDevice = sp::make("test", mModule, nullptr /*vext*/); } void TearDown() override { mDevice.clear(); @@ -251,3 +439,169 @@ TEST_F(DeviceHalAidlTest, ScreenRotation) { mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42))); EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation()); } + +// Without a vendor extension, any unrecognized parameters must be ignored. +TEST_F(DeviceHalAidlTest, VendorParameterIgnored) { + EXPECT_EQ(0UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(0UL, mModule->getSyncParameters().size()); + EXPECT_EQ(OK, mDevice->setParameters(createParameterString("random_name", "random_value"))); + EXPECT_EQ(0UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(0UL, mModule->getSyncParameters().size()); + + EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size()); + String8 values; + EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values)); + EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size()); + EXPECT_TRUE(values.empty()); +} + +class DeviceHalAidlVendorParametersTest : public testing::Test { + public: + void SetUp() override { + mModule = ndk::SharedRefBase::make(); + mVendorExt = ndk::SharedRefBase::make(); + mDevice = sp::make("test", mModule, mVendorExt); + } + void TearDown() override { + mDevice.clear(); + mVendorExt.reset(); + mModule.reset(); + } + + protected: + std::shared_ptr mModule; + std::shared_ptr mVendorExt; + sp mDevice; +}; + +TEST_F(DeviceHalAidlVendorParametersTest, GetVendorParameter) { + EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size()); + String8 values; + EXPECT_EQ(OK, mDevice->getParameters( + String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), + &values)); + EXPECT_EQ(1UL, mModule->getRetrievedParameterIds().size()); + if (mModule->getRetrievedParameterIds().size() >= 1) { + EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId, + mModule->getRetrievedParameterIds()[0]); + } +} + +TEST_F(DeviceHalAidlVendorParametersTest, SetVendorParameter) { + EXPECT_EQ(0UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(0UL, mModule->getSyncParameters().size()); + EXPECT_EQ(OK, mDevice->setParameters(createParameterString( + TestHalAdapterVendorExtension::kLegacyParameterKey, 42))); + EXPECT_EQ(0UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(1UL, mModule->getSyncParameters().size()); + EXPECT_EQ(OK, mDevice->setParameters(createParameterString( + TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43))); + EXPECT_EQ(1UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(1UL, mModule->getSyncParameters().size()); + if (mModule->getSyncParameters().size() >= 1) { + EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId, + mModule->getSyncParameters()[0].id); + int value{}; + EXPECT_EQ(android::OK, parseVendorParameter(mModule->getSyncParameters()[0], &value)); + EXPECT_EQ(42, value); + } + if (mModule->getAsyncParameters().size() >= 1) { + EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId, + mModule->getAsyncParameters()[0].id); + int value{}; + EXPECT_EQ(android::OK, parseVendorParameter(mModule->getAsyncParameters()[0], &value)); + EXPECT_EQ(43, value); + } +} + +TEST_F(DeviceHalAidlVendorParametersTest, SetInvalidVendorParameters) { + android::AudioParameter legacy; + legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42); + legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()), + 43); + legacy.addInt(android::String8("random_name"), 44); + EXPECT_EQ(0UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(0UL, mModule->getSyncParameters().size()); + // TestHalAdapterVendorExtension throws an error for unknown parameters. + EXPECT_EQ(android::BAD_VALUE, mDevice->setParameters(legacy.toString())); + EXPECT_EQ(0UL, mModule->getAsyncParameters().size()); + EXPECT_EQ(0UL, mModule->getSyncParameters().size()); +} + +class StreamHalAidlVendorParametersTest : public testing::Test { + public: + void SetUp() override { + mStreamCommon = ndk::SharedRefBase::make(); + mVendorExt = ndk::SharedRefBase::make(); + struct audio_config config = AUDIO_CONFIG_INITIALIZER; + ::aidl::android::hardware::audio::core::StreamDescriptor descriptor; + mStream = sp::make("test", false /*isInput*/, config, 0 /*nominalLatency*/, + StreamContextAidl(descriptor, false /*isAsynchronous*/), + mStreamCommon, mVendorExt); + } + void TearDown() override { + mStream.clear(); + mVendorExt.reset(); + mStreamCommon.reset(); + } + + protected: + std::shared_ptr mStreamCommon; + std::shared_ptr mVendorExt; + sp mStream; +}; + +TEST_F(StreamHalAidlVendorParametersTest, GetVendorParameter) { + EXPECT_EQ(0UL, mStreamCommon->getRetrievedParameterIds().size()); + String8 values; + EXPECT_EQ(OK, mStream->getParameters( + String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), + &values)); + EXPECT_EQ(1UL, mStreamCommon->getRetrievedParameterIds().size()); + if (mStreamCommon->getRetrievedParameterIds().size() >= 1) { + EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId, + mStreamCommon->getRetrievedParameterIds()[0]); + } +} + +TEST_F(StreamHalAidlVendorParametersTest, SetVendorParameter) { + EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size()); + EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size()); + EXPECT_EQ(OK, mStream->setParameters(createParameterString( + TestHalAdapterVendorExtension::kLegacyParameterKey, 42))); + EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size()); + EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size()); + EXPECT_EQ(OK, mStream->setParameters(createParameterString( + TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43))); + EXPECT_EQ(1UL, mStreamCommon->getAsyncParameters().size()); + EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size()); + if (mStreamCommon->getSyncParameters().size() >= 1) { + EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId, + mStreamCommon->getSyncParameters()[0].id); + int value{}; + EXPECT_EQ(android::OK, parseVendorParameter(mStreamCommon->getSyncParameters()[0], &value)); + EXPECT_EQ(42, value); + } + if (mStreamCommon->getAsyncParameters().size() >= 1) { + EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId, + mStreamCommon->getAsyncParameters()[0].id); + int value{}; + EXPECT_EQ(android::OK, + parseVendorParameter(mStreamCommon->getAsyncParameters()[0], &value)); + EXPECT_EQ(43, value); + } +} + +TEST_F(StreamHalAidlVendorParametersTest, SetInvalidVendorParameters) { + android::AudioParameter legacy; + legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42); + legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()), + 43); + legacy.addInt(android::String8("random_name"), 44); + EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size()); + EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size()); + // TestHalAdapterVendorExtension throws an error for unknown parameters. + EXPECT_EQ(android::BAD_VALUE, mStream->setParameters(legacy.toString())); + EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size()); + EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size()); +} From 6acf34b4046b8a18a92b61d9d68ea59e2efbf78d Mon Sep 17 00:00:00 2001 From: Oscar Azucena Date: Thu, 27 Apr 2023 16:32:09 -0700 Subject: [PATCH 011/148] Added skip delays when activating user id device affinities Bug: 269208752 Test: Ran MU workflow observed 90% reduction in audio routing (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:299565553494ad0fbe38d0c737e3140057552fce) Merged-In: I000369822c82ac38ff7008fafab8bc569bd762a2 Change-Id: I000369822c82ac38ff7008fafab8bc569bd762a2 --- .../include/AudioOutputDescriptor.h | 9 +++ .../include/AudioPolicyMix.h | 2 +- .../src/AudioOutputDescriptor.cpp | 5 ++ .../managerdefinitions/src/AudioPolicyMix.cpp | 4 +- .../managerdefault/AudioPolicyManager.cpp | 76 ++++++++++++++++--- .../managerdefault/AudioPolicyManager.h | 25 +++++- 6 files changed, 103 insertions(+), 18 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index 876911d576..febccac3e6 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -423,6 +423,15 @@ class SwAudioOutputDescriptor: public AudioOutputDescriptor */ bool supportsAllDevices(const DeviceVector &devices) const; + /** + * @brief supportsAtLeastOne checks if any device in devices is currently supported + * @param devices to be checked against + * @return true if the device is weakly supported by type (e.g. for non bus / rsubmix devices), + * true if the device is supported (both type and address) for bus / remote submix + * false otherwise + */ + bool supportsAtLeastOne(const DeviceVector &devices) const; + /** * @brief supportsDevicesForPlayback * @param devices to be checked against diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h index 92292e1faa..7e29e10a1a 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h @@ -138,7 +138,7 @@ class AudioPolicyMixCollection : public Vector> */ status_t setUserIdDeviceAffinities(int userId, const AudioDeviceTypeAddrVector& devices); status_t removeUserIdDeviceAffinities(int userId); - status_t getDevicesForUserId(int userId, Vector& devices) const; + status_t getDevicesForUserId(int userId, AudioDeviceTypeAddrVector& devices) const; void dump(String8 *dst) const; diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 09ca9898b4..ac1f8b2b29 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -389,6 +389,11 @@ bool SwAudioOutputDescriptor::supportsAllDevices(const DeviceVector &devices) co return supportedDevices().containsAllDevices(devices); } +bool SwAudioOutputDescriptor::supportsAtLeastOne(const DeviceVector &devices) const +{ + return filterSupportedDevices(devices).size() > 0; +} + bool SwAudioOutputDescriptor::supportsDevicesForPlayback(const DeviceVector &devices) const { // No considering duplicated output diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp index 4cfdaad5ce..631fff8c17 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp @@ -640,7 +640,7 @@ status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) { } status_t AudioPolicyMixCollection::getDevicesForUserId(int userId, - Vector& devices) const { + AudioDeviceTypeAddrVector& devices) const { // for each player mix: // find rules that don't exclude this userId, and add the device to the list for (size_t i = 0; i < size(); i++) { @@ -658,7 +658,7 @@ status_t AudioPolicyMixCollection::getDevicesForUserId(int userId, } } if (ruleAllowsUserId) { - devices.add(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string())); + devices.push_back(AudioDeviceTypeAddr(mix->mDeviceType, mix->mDeviceAddress.string())); } } return NO_ERROR; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 7d667d5400..4e758cc14f 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -3783,6 +3783,44 @@ bool AudioPolicyManager::areAllDevicesSupported( return true; } +void AudioPolicyManager::changeOutputDevicesMuteState( + const AudioDeviceTypeAddrVector& devices) { + ALOGVV("%s() num devices %zu", __func__, devices.size()); + + std::vector> outputs = + getSoftwareOutputsForDevices(devices); + + for (size_t i = 0; i < outputs.size(); i++) { + sp outputDesc = outputs[i]; + DeviceVector prevDevices = outputDesc->devices(); + checkDeviceMuteStrategies(outputDesc, prevDevices, 0 /* delayMs */); + } +} + +std::vector> AudioPolicyManager::getSoftwareOutputsForDevices( + const AudioDeviceTypeAddrVector& devices) const +{ + std::vector> outputs; + DeviceVector deviceDescriptors; + for (size_t j = 0; j < devices.size(); j++) { + sp desc = mHwModules.getDeviceDescriptor( + devices[j].mType, devices[j].getAddress(), String8(), AUDIO_FORMAT_DEFAULT); + if (desc == nullptr || !audio_is_output_device(devices[j].mType)) { + ALOGE("%s: device type %#x address %s not supported or not an output device", + __func__, devices[j].mType, devices[j].getAddress()); + continue; + } + deviceDescriptors.add(desc); + } + for (size_t i = 0; i < mOutputs.size(); i++) { + if (!mOutputs.valueAt(i)->supportsAtLeastOne(deviceDescriptors)) { + continue; + } + outputs.push_back(mOutputs.valueAt(i)); + } + return outputs; +} + status_t AudioPolicyManager::setUidDeviceAffinities(uid_t uid, const AudioDeviceTypeAddrVector& devices) { ALOGV("%s() uid=%d num devices %zu", __FUNCTION__, uid, devices.size()); @@ -3849,7 +3887,8 @@ status_t AudioPolicyManager::setDevicesRoleForStrategy(product_strategy_t strate return NO_ERROR; } -void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs) +void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint32_t delayMs, + bool skipDelays) { uint32_t waitMs = 0; bool wasLeUnicastActive = isLeUnicastActive(); @@ -3875,8 +3914,8 @@ void AudioPolicyManager::updateCallAndOutputRouting(bool forceVolumeReeval, uint continue; } waitMs = setOutputDevices(outputDesc, newDevices, forceRouting, delayMs, nullptr, - true /*requiresMuteCheck*/, - !forceRouting /*requiresVolumeCheck*/); + !skipDelays /*requiresMuteCheck*/, + !forceRouting /*requiresVolumeCheck*/, skipDelays); // Only apply special touch sound delay once delayMs = 0; } @@ -4061,13 +4100,18 @@ status_t AudioPolicyManager::setUserIdDeviceAffinities(int userId, // reevaluate outputs for all devices checkForDeviceAndOutputChanges(); - updateCallAndOutputRouting(); + changeOutputDevicesMuteState(devices); + updateCallAndOutputRouting(false /* forceVolumeReeval */, 0 /* delayMs */, + true /* skipDelays */); + changeOutputDevicesMuteState(devices); return NO_ERROR; } status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) { ALOGV("%s() userId=%d", __FUNCTION__, userId); + AudioDeviceTypeAddrVector devices; + mPolicyMixes.getDevicesForUserId(userId, devices); status_t status = mPolicyMixes.removeUserIdDeviceAffinities(userId); if (status != NO_ERROR) { ALOGE("%s() Could not remove all device affinities fo userId = %d", @@ -4077,7 +4121,10 @@ status_t AudioPolicyManager::removeUserIdDeviceAffinities(int userId) { // reevaluate outputs for all devices checkForDeviceAndOutputChanges(); - updateCallAndOutputRouting(); + changeOutputDevicesMuteState(devices); + updateCallAndOutputRouting(false /* forceVolumeReeval */, 0 /* delayMs */, + true /* skipDelays */); + changeOutputDevicesMuteState(devices); return NO_ERROR; } @@ -7324,7 +7371,8 @@ uint32_t AudioPolicyManager::setOutputDevices(const sp& bool force, int delayMs, audio_patch_handle_t *patchHandle, - bool requiresMuteCheck, bool requiresVolumeCheck) + bool requiresMuteCheck, bool requiresVolumeCheck, + bool skipMuteDelay) { // TODO(b/262404095): Consider if the output need to be reopened. ALOGV("%s device %s delayMs %d", __func__, devices.toString().c_str(), delayMs); @@ -7332,9 +7380,9 @@ uint32_t AudioPolicyManager::setOutputDevices(const sp& if (outputDesc->isDuplicated()) { muteWaitMs = setOutputDevices(outputDesc->subOutput1(), devices, force, delayMs, - nullptr /* patchHandle */, requiresMuteCheck); + nullptr /* patchHandle */, requiresMuteCheck, skipMuteDelay); muteWaitMs += setOutputDevices(outputDesc->subOutput2(), devices, force, delayMs, - nullptr /* patchHandle */, requiresMuteCheck); + nullptr /* patchHandle */, requiresMuteCheck, skipMuteDelay); return muteWaitMs; } @@ -7400,12 +7448,16 @@ uint32_t AudioPolicyManager::setOutputDevices(const sp& // Add half reported latency to delayMs when muteWaitMs is null in order // to avoid disordered sequence of muting volume and changing devices. - installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), - muteWaitMs == 0 ? (delayMs + (outputDesc->latency() / 2)) : delayMs); + int actualDelayMs = !skipMuteDelay && muteWaitMs == 0 + ? (delayMs + (outputDesc->latency() / 2)) : delayMs; + installPatch(__func__, patchHandle, outputDesc.get(), patchBuilder.patch(), actualDelayMs); } - // update stream volumes according to new device - applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs); + // Since the mute is skip, also skip the apply stream volume as that will be applied externally + if (!skipMuteDelay) { + // update stream volumes according to new device + applyStreamVolumes(outputDesc, filteredDevices.types(), delayMs); + } return muteWaitMs; } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index 98988e7701..863c785b08 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -535,8 +535,9 @@ class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManage * and currently active, allow to have proper drain and avoid pops * @param requiresVolumeCheck true if called requires to reapply volume if the routing did * not change (but the output is still routed). + * @param skipMuteDelay if true will skip mute delay when installing audio patch * @return the number of ms we have slept to allow new routing to take effect in certain - * cases. + * cases. */ uint32_t setOutputDevices(const sp& outputDesc, const DeviceVector &device, @@ -544,7 +545,8 @@ class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManage int delayMs = 0, audio_patch_handle_t *patchHandle = NULL, bool requiresMuteCheck = true, - bool requiresVolumeCheck = false); + bool requiresVolumeCheck = false, + bool skipMuteDelay = false); status_t resetOutputDevice(const sp& outputDesc, int delayMs = 0, audio_patch_handle_t *patchHandle = NULL); @@ -647,8 +649,10 @@ class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManage /** * @brief updates routing for all outputs (including call if call in progress). * @param delayMs delay for unmuting if required + * @param skipDelays if true all the delays will be skip while updating routing */ - void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0); + void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0, + bool skipDelays = false); bool isCallRxAudioSource(const sp &source) { return mCallRxSourceClient != nullptr && source == mCallRxSourceClient; @@ -1241,6 +1245,21 @@ class AudioPolicyManager : public AudioPolicyInterface, public AudioPolicyManage const char* context, bool matchAddress = true); + /** + * @brief changeOutputDevicesMuteState mute/unmute devices using checkDeviceMuteStrategies + * @param devices devices to mute/unmute + */ + void changeOutputDevicesMuteState(const AudioDeviceTypeAddrVector& devices); + + /** + * @brief Returns a vector of software output descriptor that support the queried devices + * @param devices devices to query + * @param openOutputs open outputs where the devices are supported as determined by + * SwAudioOutputDescriptor::supportsAtLeastOne + */ + std::vector> getSoftwareOutputsForDevices( + const AudioDeviceTypeAddrVector& devices) const; + bool isScoRequestedForComm() const; bool isHearingAidUsedForComm() const; From 1579be6d8afe1d369744b0153b5254b655e993e0 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Mon, 12 Jun 2023 17:01:10 -0700 Subject: [PATCH 012/148] Send 'closing=true' from StreamOutHalHidl::exit Combine sending of 'closing=true' with 'exiting=1' for legacy HALs. Historically, the remote submix HAL was using a separate notification because initially 'closing=true' was only sent for the A2DP output. Unify sending of these parameters as in the AIDL HAL interface we only use the thread exiting condition to notify the HAL about the need to stop its output. Bug: 73175392 Test: manual check of A2DP connection, disconnection, switching "Mono audio" on and off; manual check of screen recording with audio Change-Id: I722e5dadbab252ccae29eedad92e568ffe664b4d --- media/libaudiohal/impl/StreamHalHidl.cpp | 3 ++- media/libmediahelper/include/media/AudioParameter.h | 3 +-- .../common/managerdefinitions/src/AudioOutputDescriptor.cpp | 6 ------ 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp index 2b0af49c16..82062cc983 100644 --- a/media/libaudiohal/impl/StreamHalHidl.cpp +++ b/media/libaudiohal/impl/StreamHalHidl.cpp @@ -979,9 +979,10 @@ void StreamOutHalHidl::onRecommendedLatencyModeChanged( } status_t StreamOutHalHidl::exit() { - // Signal exiting to remote_submix HAL. + // Signal exiting to HALs that use intermediate pipes to close them. AudioParameter param; param.addInt(String8(AudioParameter::keyExiting), 1); + param.add(String8(AudioParameter::keyClosing), String8(AudioParameter::valueTrue)); return setParameters(param.toString()); } diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h index 8568b8fcd1..3eee854f74 100644 --- a/media/libmediahelper/include/media/AudioParameter.h +++ b/media/libmediahelper/include/media/AudioParameter.h @@ -51,8 +51,7 @@ class AudioParameter { 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. + // keyClosing: "true" on AudioFlinger Thread preExit. Used by A2DP HAL. // keyExiting: "1" on AudioFlinger Thread preExit. Used by remote_submix and A2DP HAL. static const char * const keyClosing; static const char * const keyExiting; diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index ac1f8b2b29..8b2331112e 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -706,12 +706,6 @@ void SwAudioOutputDescriptor::close() } } - // TODO(b/73175392) consider improving the AIDL interface. - // Signal closing to A2DP HAL. - AudioParameter param; - param.add(String8(AudioParameter::keyClosing), String8("true")); - mClientInterface->setParameters(mIoHandle, param.toString()); - mClientInterface->closeOutput(mIoHandle); LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u", From e3d1f553de5a36bf7f352d372b01bab8e6f85316 Mon Sep 17 00:00:00 2001 From: jiabin Date: Wed, 14 Jun 2023 17:42:17 +0000 Subject: [PATCH 013/148] Invalidate all other clients when bit-perfect playback becomes active. When bit-perfect playback becomes active, the framework should ensure there is only one active stream so that the HAL knows which configuration to open the sink. In that case, when bit-perfect playback become active, invalidate all clients that will then be routed to bit-perfect sink. Bug: 287088377 Test: atest audiopolicy_tests Change-Id: Iadf207d273e2301f5976b48dbd2f08f859473226 --- .../managerdefault/AudioPolicyManager.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 4e758cc14f..3f2b19664c 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -2148,6 +2148,26 @@ status_t AudioPolicyManager::startOutput(audio_port_handle_t portId) return DEAD_OBJECT; } info->increaseActiveClient(); + if (info->getActiveClientCount() == 1 && + (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE) { + // If it is first bit-perfect client, reroute all clients that will be routed to + // the bit-perfect sink so that it is guaranteed only bit-perfect stream is active. + PortHandleVector clientsToInvalidate; + for (size_t i = 0; i < mOutputs.size(); i++) { + if (mOutputs[i] == outputDesc || + !mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty()) { + continue; + } + for (const auto& c : mOutputs[i]->getClientIterable()) { + clientsToInvalidate.push_back(c->portId()); + } + } + if (!clientsToInvalidate.empty()) { + ALOGD("%s Invalidate clients due to first bit-perfect client started", + __func__); + mpClientInterface->invalidateTracks(clientsToInvalidate); + } + } } } From 9b8fecba60efbbf5f787f057796a9df90eeab45f Mon Sep 17 00:00:00 2001 From: jiabin Date: Thu, 15 Jun 2023 19:57:57 +0000 Subject: [PATCH 014/148] APM: avoid adding duplicated audio profile. When reopening output, APM may add duplicated audio profiles. This can happen when clients start and stop playback with preferred mixer attributes. Bug: 287502159 Test: compare audio policy dumpsys Change-Id: I2ffb3de3940c3ca46703b56f9ee5afb2872f3465 --- .../src/AudioProfileVectorHelper.cpp | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp index 8ccb8b905b..82f51ad1bf 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioProfileVectorHelper.cpp @@ -115,12 +115,22 @@ void addProfilesForFormats(AudioProfileVector &audioProfileVector, const FormatV profile->setDynamicFormat(true); profile->setDynamicChannels(dynamicFormatProfile->isDynamicChannels()); profile->setDynamicRate(dynamicFormatProfile->isDynamicRate()); - addAudioProfileAndSort(audioProfileVector, profile); + size_t profileIndex = 0; + for (; profileIndex < audioProfileVector.size(); profileIndex++) { + if (profile->equals(audioProfileVector.at(profileIndex))) { + // The dynamic profile is already there + break; + } + } + if (profileIndex >= audioProfileVector.size()) { + // Only add when the dynamic profile is not there + addAudioProfileAndSort(audioProfileVector, profile); + } } } void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector, - const sp &profileToAdd) + const sp &profileToAdd) { // Check valid profile to add: if (!profileToAdd->hasValidFormat()) { @@ -143,11 +153,15 @@ void addDynamicAudioProfileAndSort(AudioProfileVector &audioProfileVector, audioProfileVector, profileToAdd->getChannels(), profileToAdd->getFormat()); return; } + const bool originalIsDynamicFormat = profileToAdd->isDynamicFormat(); + profileToAdd->setDynamicFormat(true); // set the format as dynamic to allow removal // Go through the list of profile to avoid duplicates for (size_t profileIndex = 0; profileIndex < audioProfileVector.size(); profileIndex++) { const sp &profile = audioProfileVector.at(profileIndex); - if (profile->isValid() && profile == profileToAdd) { - // Nothing to do + if (profile->isValid() && profile->equals(profileToAdd)) { + // The same profile is already there, no need to add. + // Reset `isDynamicProfile` as original value. + profileToAdd->setDynamicFormat(originalIsDynamicFormat); return; } } From 779fdf6c99d487d768ed7aac353c4a7f3ad5bc5d Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 14 Jun 2023 15:49:59 -0700 Subject: [PATCH 015/148] Clean up EffectHalInterface Remove `isLocal`, it's a legacy from the HIDL transition times. Make `effectId` specific to EffectHalHidl, remove usages outside of libaudiohal. Bug: 205884982 Test: m Change-Id: I0486d5fb48d8cfce46aca9152136e7a1a68cf215 Merged-In: I0486d5fb48d8cfce46aca9152136e7a1a68cf215 --- media/libaudiohal/impl/DeviceHalHidl.cpp | 7 +++++-- media/libaudiohal/impl/EffectConversionHelperHidl.h | 4 ++-- media/libaudiohal/impl/EffectHalAidl.cpp | 3 +-- media/libaudiohal/impl/EffectHalAidl.h | 8 +------- media/libaudiohal/impl/EffectHalHidl.h | 9 +++------ media/libaudiohal/impl/EffectsFactoryHalAidl.cpp | 9 +-------- media/libaudiohal/impl/EffectsFactoryHalAidl.h | 4 ---- media/libaudiohal/impl/StreamHalHidl.cpp | 7 +++++-- .../include/media/audiohal/EffectHalInterface.h | 10 ++-------- services/audiopolicy/service/Spatializer.cpp | 9 +++------ 10 files changed, 23 insertions(+), 47 deletions(-) diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp index 826461f9a5..a717327336 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.cpp +++ b/media/libaudiohal/impl/DeviceHalHidl.cpp @@ -32,6 +32,7 @@ #include #include "DeviceHalHidl.h" +#include "EffectHalHidl.h" #include "ParameterUtils.h" #include "StreamHalHidl.h" @@ -526,8 +527,9 @@ status_t DeviceHalHidl::addDeviceEffect( audio_port_handle_t device, sp effect) { TIME_CHECK(); if (mDevice == 0) return NO_INIT; + auto hidlEffect = sp::cast(effect); return processReturn("addDeviceEffect", mDevice->addDeviceEffect( - static_cast(device), effect->effectId())); + static_cast(device), hidlEffect->effectId())); } #else status_t DeviceHalHidl::addDeviceEffect( @@ -541,8 +543,9 @@ status_t DeviceHalHidl::removeDeviceEffect( audio_port_handle_t device, sp effect) { TIME_CHECK(); if (mDevice == 0) return NO_INIT; + auto hidlEffect = sp::cast(effect); return processReturn("removeDeviceEffect", mDevice->removeDeviceEffect( - static_cast(device), effect->effectId())); + static_cast(device), hidlEffect->effectId())); } #else status_t DeviceHalHidl::removeDeviceEffect( diff --git a/media/libaudiohal/impl/EffectConversionHelperHidl.h b/media/libaudiohal/impl/EffectConversionHelperHidl.h index 4371d1204f..ed696bf384 100644 --- a/media/libaudiohal/impl/EffectConversionHelperHidl.h +++ b/media/libaudiohal/impl/EffectConversionHelperHidl.h @@ -19,9 +19,9 @@ #include "ConversionHelperHidl.h" -#include PATH(android/hardware/audio/effect/FILE_VERSION/types.h) +#include PATH(android/hardware/audio/effect/COMMON_TYPES_FILE_VERSION/types.h) -using EffectResult = ::android::hardware::audio::effect::CPP_VERSION::Result; +using EffectResult = ::android::hardware::audio::effect::COMMON_TYPES_CPP_VERSION::Result; namespace android { diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp index faf5f45517..b9d9541f4e 100644 --- a/media/libaudiohal/impl/EffectHalAidl.cpp +++ b/media/libaudiohal/impl/EffectHalAidl.cpp @@ -61,12 +61,11 @@ namespace android { namespace effect { EffectHalAidl::EffectHalAidl(const std::shared_ptr& factory, - const std::shared_ptr& effect, uint64_t effectId, + const std::shared_ptr& effect, int32_t sessionId, int32_t ioId, const Descriptor& desc, bool isProxyEffect) : mFactory(factory), mEffect(effect), - mEffectId(effectId), mSessionId(sessionId), mIoId(ioId), mDesc(desc), diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h index 47049d7775..1b7a3d6166 100644 --- a/media/libaudiohal/impl/EffectHalAidl.h +++ b/media/libaudiohal/impl/EffectHalAidl.h @@ -56,13 +56,8 @@ class EffectHalAidl : public EffectHalInterface { // Free resources on the remote side. status_t close() override; - // Whether it's a local implementation. - bool isLocal() const override { return false; } - status_t dump(int fd) override; - uint64_t effectId() const override { return mEffectId; } - const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> getIEffect() const { return mEffect; } @@ -75,7 +70,6 @@ class EffectHalAidl : public EffectHalInterface { const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory; const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect; - const uint64_t mEffectId; const int32_t mSessionId; const int32_t mIoId; const ::aidl::android::hardware::audio::effect::Descriptor mDesc; @@ -93,7 +87,7 @@ class EffectHalAidl : public EffectHalInterface { EffectHalAidl( const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory, const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& effect, - uint64_t effectId, int32_t sessionId, int32_t ioId, + int32_t sessionId, int32_t ioId, const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect); bool setEffectReverse(bool reverse); diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h index 94dcd7eebb..dda21ed2cf 100644 --- a/media/libaudiohal/impl/EffectHalHidl.h +++ b/media/libaudiohal/impl/EffectHalHidl.h @@ -17,7 +17,7 @@ #ifndef ANDROID_HARDWARE_EFFECT_HAL_HIDL_H #define ANDROID_HARDWARE_EFFECT_HAL_HIDL_H -#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffect.h) +#include PATH(android/hardware/audio/effect/COMMON_TYPES_FILE_VERSION/IEffect.h) #include #include #include @@ -31,7 +31,7 @@ using ::android::hardware::MessageQueue; namespace android { namespace effect { -using namespace ::android::hardware::audio::effect::CPP_VERSION; +using namespace ::android::hardware::audio::effect::COMMON_TYPES_CPP_VERSION; class EffectHalHidl : public EffectHalInterface, public EffectConversionHelperHidl { @@ -59,12 +59,9 @@ class EffectHalHidl : public EffectHalInterface, public EffectConversionHelperHi // Free resources on the remote side. virtual status_t close(); - // Whether it's a local implementation. - virtual bool isLocal() const { return false; } - virtual status_t dump(int fd); - virtual uint64_t effectId() const { return mEffectId; } + uint64_t effectId() const { return mEffectId; } private: friend class EffectsFactoryHalHidl; diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp index 7b9088e16d..7ff74df42d 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp @@ -194,14 +194,7 @@ status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t Descriptor desc; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc))); - uint64_t effectId; - { - std::lock_guard lg(mLock); - effectId = ++mEffectIdCounter; - } - - *effect = - sp::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc, isProxy); + *effect = sp::make(mFactory, aidlEffect, sessionId, ioId, desc, isProxy); return OK; } diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h index 39beea275b..9fae9d4671 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -85,9 +84,6 @@ class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface { // Query result of pre and post processing from effect factory const std::vector mAidlProcessings; - std::mutex mLock; - uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID) - virtual ~EffectsFactoryHalAidl() = default; status_t getHalDescriptorWithImplUuid( const aidl::android::media::audio::common::AudioUuid& uuid, diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp index 82062cc983..72eadc604c 100644 --- a/media/libaudiohal/impl/StreamHalHidl.cpp +++ b/media/libaudiohal/impl/StreamHalHidl.cpp @@ -33,6 +33,7 @@ #include #include "DeviceHalHidl.h" +#include "EffectHalHidl.h" #include "ParameterUtils.h" #include "StreamHalHidl.h" @@ -144,13 +145,15 @@ status_t StreamHalHidl::getParameters(const String8& keys, String8 *values) { status_t StreamHalHidl::addEffect(sp effect) { TIME_CHECK(); if (!mStream) return NO_INIT; - return processReturn("addEffect", mStream->addEffect(effect->effectId())); + auto hidlEffect = sp::cast(effect); + return processReturn("addEffect", mStream->addEffect(hidlEffect->effectId())); } status_t StreamHalHidl::removeEffect(sp effect) { TIME_CHECK(); if (!mStream) return NO_INIT; - return processReturn("removeEffect", mStream->removeEffect(effect->effectId())); + auto hidlEffect = sp::cast(effect); + return processReturn("removeEffect", mStream->removeEffect(hidlEffect->effectId())); } status_t StreamHalHidl::standby() { diff --git a/media/libaudiohal/include/media/audiohal/EffectHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h index 2969c9248d..cf8d7f048e 100644 --- a/media/libaudiohal/include/media/audiohal/EffectHalInterface.h +++ b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h @@ -52,20 +52,14 @@ class EffectHalInterface : public RefBase // Free resources on the remote side. virtual status_t close() = 0; - // Whether it's a local implementation. - virtual bool isLocal() const = 0; - virtual status_t dump(int fd) = 0; - // Unique effect ID to use with the core HAL. - virtual uint64_t effectId() const = 0; - protected: // Subclasses can not be constructed directly by clients. - EffectHalInterface() {} + EffectHalInterface() = default; // The destructor automatically releases the effect. - virtual ~EffectHalInterface() {} + virtual ~EffectHalInterface() = default; }; } // namespace android diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp index ee2e0ebf9d..1245b1ef39 100644 --- a/services/audiopolicy/service/Spatializer.cpp +++ b/services/audiopolicy/service/Spatializer.cpp @@ -236,18 +236,15 @@ sp Spatializer::create(SpatializerPolicyCallback* callback, sp effect; status = effectsFactoryHal->createEffect(&descriptors[0].uuid, AUDIO_SESSION_OUTPUT_STAGE, AUDIO_IO_HANDLE_NONE, AUDIO_PORT_HANDLE_NONE, &effect); - ALOGI("%s FX create status %d effect ID %" PRId64, __func__, status, - effect ? effect->effectId() : 0); + ALOGI("%s FX create status %d effect %p", __func__, status, effect.get()); if (status == NO_ERROR && effect != nullptr) { spatializer = new Spatializer(descriptors[0], callback); if (spatializer->loadEngineConfiguration(effect) != NO_ERROR) { spatializer.clear(); - ALOGW("%s loadEngine error: %d effect Id %" PRId64, - __func__, status, effect ? effect->effectId() : 0); + ALOGW("%s loadEngine error: %d effect %p", __func__, status, effect.get()); } else { - spatializer->mLocalLog.log("%s with effect Id %" PRId64, __func__, - effect ? effect->effectId() : 0); + spatializer->mLocalLog.log("%s with effect Id %p", __func__, effect.get()); } } From 570ce38d300bce8d59b63ba063870c4373b2715a Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 14 Jun 2023 18:00:13 -0700 Subject: [PATCH 016/148] Use 'audio_port_config' in DeviceHalInterface::add/removeDeviceEffect Previously, `audio_port_handle_t` was used to specify the device port. However, these port handles are allocated by the framework and are not known to the HAL a priori. The current scenario assumes that the framework first creates an audio patch, thus passes a complete `audio_port_config` to the HAL prior to adding an effect. However, this assumption isn't stated anywhere in the legacy interface definition. To make things more flexible, make the framework to pass `audio_port_config` when it adds/removes a device effect. This also makes unnecessary to pass the hw module ID as it is contained within the port config. The legacy HAL interface is left intact. Bug: 205884982 Test: m Change-Id: Ie9410637ad092bff22b2c0fe1c92e516a1f24ee0 Merged-In: Ie9410637ad092bff22b2c0fe1c92e516a1f24ee0 --- media/libaudiohal/impl/DeviceHalAidl.cpp | 4 ++-- media/libaudiohal/impl/DeviceHalAidl.h | 6 ++++-- media/libaudiohal/impl/DeviceHalHidl.cpp | 12 +++++------ media/libaudiohal/impl/DeviceHalHidl.h | 6 ++++-- .../media/audiohal/DeviceHalInterface.h | 4 ++-- services/audioflinger/AudioFlinger.cpp | 16 +++++++-------- services/audioflinger/AudioFlinger.h | 8 ++++---- services/audioflinger/DeviceEffectManager.h | 20 +++++++++---------- services/audioflinger/Effects.cpp | 6 ++---- 9 files changed, 42 insertions(+), 40 deletions(-) diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index b1b7e00db6..06c5f53fb5 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -882,7 +882,7 @@ status_t DeviceHalAidl::getMicrophones( return OK; } -status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused, +status_t DeviceHalAidl::addDeviceEffect(const struct audio_port_config *device __unused, sp effect) { if (!effect) { return BAD_VALUE; @@ -892,7 +892,7 @@ status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused, ALOGE("%s not implemented yet", __func__); return OK; } -status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused, +status_t DeviceHalAidl::removeDeviceEffect(const struct audio_port_config *device __unused, sp effect) { if (!effect) { return BAD_VALUE; diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index 03afbb7238..74a8b51bf5 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -149,9 +149,11 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, // List microphones status_t getMicrophones(std::vector* microphones) override; - status_t addDeviceEffect(audio_port_handle_t device, sp effect) override; + status_t addDeviceEffect( + const struct audio_port_config *device, sp effect) override; - status_t removeDeviceEffect(audio_port_handle_t device, sp effect) override; + status_t removeDeviceEffect( + const struct audio_port_config *device, sp effect) override; status_t getMmapPolicyInfos(media::audio::common::AudioMMapPolicyType policyType __unused, std::vector* policyInfos diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp index a717327336..f96d419393 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.cpp +++ b/media/libaudiohal/impl/DeviceHalHidl.cpp @@ -524,32 +524,32 @@ status_t DeviceHalHidl::getMicrophones( #if MAJOR_VERSION >= 6 status_t DeviceHalHidl::addDeviceEffect( - audio_port_handle_t device, sp effect) { + const struct audio_port_config *device, sp effect) { TIME_CHECK(); if (mDevice == 0) return NO_INIT; auto hidlEffect = sp::cast(effect); return processReturn("addDeviceEffect", mDevice->addDeviceEffect( - static_cast(device), hidlEffect->effectId())); + static_cast(device->id), hidlEffect->effectId())); } #else status_t DeviceHalHidl::addDeviceEffect( - audio_port_handle_t device __unused, sp effect __unused) { + const struct audio_port_config *device __unused, sp effect __unused) { return INVALID_OPERATION; } #endif #if MAJOR_VERSION >= 6 status_t DeviceHalHidl::removeDeviceEffect( - audio_port_handle_t device, sp effect) { + const struct audio_port_config *device, sp effect) { TIME_CHECK(); if (mDevice == 0) return NO_INIT; auto hidlEffect = sp::cast(effect); return processReturn("removeDeviceEffect", mDevice->removeDeviceEffect( - static_cast(device), hidlEffect->effectId())); + static_cast(device->id), hidlEffect->effectId())); } #else status_t DeviceHalHidl::removeDeviceEffect( - audio_port_handle_t device __unused, sp effect __unused) { + const struct audio_port_config *device __unused, sp effect __unused) { return INVALID_OPERATION; } #endif diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h index c5addde848..989c1f520f 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.h +++ b/media/libaudiohal/impl/DeviceHalHidl.h @@ -105,8 +105,10 @@ class DeviceHalHidl : public DeviceHalInterface, public CoreConversionHelperHidl // List microphones status_t getMicrophones(std::vector* microphones) override; - status_t addDeviceEffect(audio_port_handle_t device, sp effect) override; - status_t removeDeviceEffect(audio_port_handle_t device, sp effect) override; + status_t addDeviceEffect( + const struct audio_port_config *device, sp effect) override; + status_t removeDeviceEffect( + const struct audio_port_config *device, sp effect) override; status_t getMmapPolicyInfos( media::audio::common::AudioMMapPolicyType policyType __unused, diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h index 71e5e7ad9c..a965709908 100644 --- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h +++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h @@ -132,9 +132,9 @@ class DeviceHalInterface : public virtual RefBase std::vector* microphones) = 0; virtual status_t addDeviceEffect( - audio_port_handle_t device, sp effect) = 0; + const struct audio_port_config *device, sp effect) = 0; virtual status_t removeDeviceEffect( - audio_port_handle_t device, sp effect) = 0; + const struct audio_port_config *device, sp effect) = 0; virtual status_t getMmapPolicyInfos( media::audio::common::AudioMMapPolicyType policyType, diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 325adfa568..4d9aef2a90 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -731,24 +731,24 @@ void AudioFlinger::onExternalVibrationStop(const sp& exte } } -status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId, - audio_module_handle_t hwModuleId, const sp& effect) { +status_t AudioFlinger::addEffectToHal( + const struct audio_port_config *device, const sp& effect) { AutoMutex lock(mHardwareLock); - AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId); + AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module); if (audioHwDevice == nullptr) { return NO_INIT; } - return audioHwDevice->hwDevice()->addDeviceEffect(deviceId, effect); + return audioHwDevice->hwDevice()->addDeviceEffect(device, effect); } -status_t AudioFlinger::removeEffectFromHal(audio_port_handle_t deviceId, - audio_module_handle_t hwModuleId, const sp& effect) { +status_t AudioFlinger::removeEffectFromHal( + const struct audio_port_config *device, const sp& effect) { AutoMutex lock(mHardwareLock); - AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId); + AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module); if (audioHwDevice == nullptr) { return NO_INIT; } - return audioHwDevice->hwDevice()->removeDeviceEffect(deviceId, effect); + return audioHwDevice->hwDevice()->removeDeviceEffect(device, effect); } static const char * const audio_interfaces[] = { diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 10bfdb9b54..c3ca1b0efd 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -344,10 +344,10 @@ class AudioFlinger : public AudioFlingerServerAdapter::Delegate const sp& externalVibration); static void onExternalVibrationStop(const sp& externalVibration); - status_t addEffectToHal(audio_port_handle_t deviceId, - audio_module_handle_t hwModuleId, const sp& effect); - status_t removeEffectFromHal(audio_port_handle_t deviceId, - audio_module_handle_t hwModuleId, const sp& effect); + status_t addEffectToHal( + const struct audio_port_config *device, const sp& effect); + status_t removeEffectFromHal( + const struct audio_port_config *device, const sp& effect); void updateDownStreamPatches_l(const struct audio_patch *patch, const std::set& streams); diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h index 395781d673..b87f830b77 100644 --- a/services/audioflinger/DeviceEffectManager.h +++ b/services/audioflinger/DeviceEffectManager.h @@ -44,13 +44,13 @@ class DeviceEffectManager : public PatchCommandThread::PatchCommandListener { status_t createEffectHal(const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId, sp *effect); - status_t addEffectToHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId, + status_t addEffectToHal(const struct audio_port_config *device, const sp& effect) { - return mAudioFlinger.addEffectToHal(deviceId, hwModuleId, effect); + return mAudioFlinger.addEffectToHal(device, effect); }; - status_t removeEffectFromHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId, + status_t removeEffectFromHal(const struct audio_port_config *device, const sp& effect) { - return mAudioFlinger.removeEffectFromHal(deviceId, hwModuleId, effect); + return mAudioFlinger.removeEffectFromHal(device, effect); }; AudioFlinger& audioFlinger() const { return mAudioFlinger; } @@ -132,13 +132,13 @@ class DeviceEffectManagerCallback : public EffectCallbackInterface { int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); } - status_t addEffectToHal(audio_port_handle_t deviceId, - audio_module_handle_t hwModuleId, const sp& effect) { - return mManager.addEffectToHal(deviceId, hwModuleId, effect); + status_t addEffectToHal(const struct audio_port_config *device, + const sp& effect) { + return mManager.addEffectToHal(device, effect); } - status_t removeEffectFromHal(audio_port_handle_t deviceId, - audio_module_handle_t hwModuleId, const sp& effect) { - return mManager.removeEffectFromHal(deviceId, hwModuleId, effect); + status_t removeEffectFromHal(const struct audio_port_config *device, + const sp& effect) { + return mManager.removeEffectFromHal(device, effect); } private: DeviceEffectManager& mManager; diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 77aa8048fa..7c7548ae92 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -3486,8 +3486,7 @@ status_t AudioFlinger::DeviceEffectProxy::addEffectToHal( if (mHalEffect == nullptr) { return NO_INIT; } - return mManagerCallback->addEffectToHal( - mDevicePort.id, mDevicePort.ext.device.hw_module, effect); + return mManagerCallback->addEffectToHal(&mDevicePort, effect); } status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal( @@ -3495,8 +3494,7 @@ status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal( if (mHalEffect == nullptr) { return NO_INIT; } - return mManagerCallback->removeEffectFromHal( - mDevicePort.id, mDevicePort.ext.device.hw_module, effect); + return mManagerCallback->removeEffectFromHal(&mDevicePort, effect); } bool AudioFlinger::DeviceEffectProxy::isOutput() const { From 0a90b18c4a5f196bfbbf6884152aa446b49d87e7 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 14 Jun 2023 16:31:32 -0700 Subject: [PATCH 017/148] libaudiohal@aidl: Implement effects adding/removal Implement `IModule.add/removeDeviceEffect` and `IStreamCommon.add/removeEffect`. Bug: 205884982 Test: atest com.google.android.audio.gts.DeviceEffectTest (cherry picked from https://android-review.googlesource.com/q/commit:a82a69d82a4efdc2531cc16f75daffa7eb1f1593) Merged-In: Ibb6d58222568057423579a05e0dca2b148f101f0 Change-Id: Ibb6d58222568057423579a05e0dca2b148f101f0 --- media/libaudiohal/impl/DeviceHalAidl.cpp | 62 +++++++++++++++++++----- media/libaudiohal/impl/StreamHalAidl.cpp | 19 +++++--- 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index 06c5f53fb5..ae151908c5 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -32,6 +32,7 @@ #include #include "DeviceHalAidl.h" +#include "EffectHalAidl.h" #include "StreamHalAidl.h" using aidl::android::aidl_utils::statusTFromBinderStatus; @@ -882,25 +883,64 @@ status_t DeviceHalAidl::getMicrophones( return OK; } -status_t DeviceHalAidl::addDeviceEffect(const struct audio_port_config *device __unused, - sp effect) { +status_t DeviceHalAidl::addDeviceEffect( + const struct audio_port_config *device, sp effect) { + TIME_CHECK(); + if (!mModule) return NO_INIT; if (!effect) { return BAD_VALUE; } - TIME_CHECK(); - if (!mModule) return NO_INIT; - ALOGE("%s not implemented yet", __func__); + bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection( + device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT; + auto requestedPortConfig = VALUE_OR_RETURN_STATUS( + ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig( + *device, isInput, 0)); + if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) { + ALOGE("%s: provided port config is not a device port config: %s", + __func__, requestedPortConfig.toString().c_str()); + return BAD_VALUE; + } + AudioPortConfig devicePortConfig; + bool created; + RETURN_STATUS_IF_ERROR(findOrCreatePortConfig( + requestedPortConfig, {} /*destinationPortIds*/, &devicePortConfig, &created)); + Cleanups cleanups; + if (created) { + cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id); + } + auto aidlEffect = sp::cast(effect); + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect( + devicePortConfig.id, aidlEffect->getIEffect()))); + cleanups.disarmAll(); return OK; } -status_t DeviceHalAidl::removeDeviceEffect(const struct audio_port_config *device __unused, - sp effect) { +status_t DeviceHalAidl::removeDeviceEffect( + const struct audio_port_config *device, sp effect) { + TIME_CHECK(); + if (!mModule) return NO_INIT; if (!effect) { return BAD_VALUE; } - TIME_CHECK(); - if (!mModule) return NO_INIT; - ALOGE("%s not implemented yet", __func__); - return OK; + bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection( + device->role, device->type)) == ::aidl::android::AudioPortDirection::INPUT; + auto requestedPortConfig = VALUE_OR_RETURN_STATUS( + ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig( + *device, isInput, 0)); + if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) { + ALOGE("%s: provided port config is not a device port config: %s", + __func__, requestedPortConfig.toString().c_str()); + return BAD_VALUE; + } + auto existingPortConfigIt = findPortConfig( + requestedPortConfig.ext.get().device); + if (existingPortConfigIt == mPortConfigs.end()) { + ALOGE("%s: could not find a configured device port for the config %s", + __func__, requestedPortConfig.toString().c_str()); + return BAD_VALUE; + } + auto aidlEffect = sp::cast(effect); + return statusTFromBinderStatus(mModule->removeDeviceEffect( + existingPortConfigIt->first, aidlEffect->getIEffect())); } status_t DeviceHalAidl::getMmapPolicyInfos( diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp index c84f80ff15..80e19a04ae 100644 --- a/media/libaudiohal/impl/StreamHalAidl.cpp +++ b/media/libaudiohal/impl/StreamHalAidl.cpp @@ -32,6 +32,7 @@ #include #include "DeviceHalAidl.h" +#include "EffectHalAidl.h" #include "StreamHalAidl.h" using ::aidl::android::aidl_utils::statusTFromBinderStatus; @@ -162,20 +163,26 @@ status_t StreamHalAidl::getFrameSize(size_t *size) { return OK; } -status_t StreamHalAidl::addEffect(sp effect __unused) { +status_t StreamHalAidl::addEffect(sp effect) { ALOGD("%p %s::%s", this, getClassName().c_str(), __func__); TIME_CHECK(); if (!mStream) return NO_INIT; - ALOGE("%s not implemented yet", __func__); - return OK; + if (effect == nullptr) { + return BAD_VALUE; + } + auto aidlEffect = sp::cast(effect); + return statusTFromBinderStatus(mStream->addEffect(aidlEffect->getIEffect())); } -status_t StreamHalAidl::removeEffect(sp effect __unused) { +status_t StreamHalAidl::removeEffect(sp effect) { ALOGD("%p %s::%s", this, getClassName().c_str(), __func__); TIME_CHECK(); if (!mStream) return NO_INIT; - ALOGE("%s not implemented yet", __func__); - return OK; + if (effect == nullptr) { + return BAD_VALUE; + } + auto aidlEffect = sp::cast(effect); + return statusTFromBinderStatus(mStream->removeEffect(aidlEffect->getIEffect())); } status_t StreamHalAidl::standby() { From 387360400c228be6323f0070a139c63163b86994 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Fri, 16 Jun 2023 15:33:39 -0700 Subject: [PATCH 018/148] Enlarge the width of AudioTimestampInternal.position Change the AIDL type of the field to `long` because it must be able to hold all values from AudioTimestamp::mPosition, which has type `uint32_t`. Bug: 287590875 Test: m Change-Id: Id0b4ab3325b5622fddae7320516f38b3e9efbe21 --- media/libaudioclient/AidlConversion.cpp | 2 +- .../aidl/android/media/AudioTimestampInternal.aidl | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp index bd10e44db0..2377fc8131 100644 --- a/media/libaudioclient/AidlConversion.cpp +++ b/media/libaudioclient/AidlConversion.cpp @@ -528,7 +528,7 @@ aidl2legacy_AudioTimestampInternal_AudioTimestamp(const media::AudioTimestampInt ConversionResult legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy) { media::AudioTimestampInternal aidl; - aidl.position = VALUE_OR_RETURN(convertIntegral(legacy.mPosition)); + aidl.position = VALUE_OR_RETURN(convertIntegral(legacy.mPosition)); aidl.sec = VALUE_OR_RETURN(convertIntegral(legacy.mTime.tv_sec)); aidl.nsec = VALUE_OR_RETURN(convertIntegral(legacy.mTime.tv_nsec)); return aidl; diff --git a/media/libaudioclient/aidl/android/media/AudioTimestampInternal.aidl b/media/libaudioclient/aidl/android/media/AudioTimestampInternal.aidl index 8bbfb57cd7..1f16525717 100644 --- a/media/libaudioclient/aidl/android/media/AudioTimestampInternal.aidl +++ b/media/libaudioclient/aidl/android/media/AudioTimestampInternal.aidl @@ -22,8 +22,11 @@ package android.media; * {@hide} */ parcelable AudioTimestampInternal { - /** A frame position in AudioTrack::getPosition() units. */ - int position; + /** + * A frame position in AudioTrack::getPosition() units. Use 'long' to accommodate + * all values from 'uint32_t'. + */ + long position; /** corresponding CLOCK_MONOTONIC when frame is expected to present. */ long sec; int nsec; From 370abecc7d9a1b9162c1580272a7369a81031fa4 Mon Sep 17 00:00:00 2001 From: Jan Sebechlebsky Date: Thu, 15 Jun 2023 10:18:30 +0200 Subject: [PATCH 019/148] Allow DAP render-only mix to be matched to mmap-ed stream. Bug: b/287182335 Test: atest audiopolicy_tests AudioHostTest Change-Id: If1e0ffb980e989cfd0fb9c6d2f87fac60ad7d067 --- .../managerdefinitions/src/AudioPolicyMix.cpp | 7 ++--- .../tests/audiopolicymanager_tests.cpp | 26 +++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp index fc1372befc..bc2ba31552 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp @@ -289,9 +289,10 @@ status_t AudioPolicyMixCollection::getOutputForAttr( continue; // skip the mix } - if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) { - // AAudio MMAP_NOIRQ streams cannot be routed using dynamic audio policy. - ALOGD("%s: Rejecting MMAP_NOIRQ request matched to dynamic audio policy mix.", + if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) && is_mix_loopback(policyMix->mRouteFlags)) { + // AAudio MMAP_NOIRQ streams cannot be routed to loopback/loopback+render + // using dynamic audio policy. + ALOGD("%s: Rejecting MMAP_NOIRQ request matched to loopback dynamic audio policy mix.", __func__); return INVALID_OPERATION; } diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp index 8dfc081aad..15eae14cb3 100644 --- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp +++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp @@ -1912,7 +1912,7 @@ class AudioPolicyManagerTestMMapPlaybackRerouting bool mIsBitPerfect; }; -TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingDapMixFails) { +TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingLoopbackDapMixFails) { // Add mix matching the test uid. const int testUid = 12345; const auto param = GetParam(); @@ -1929,7 +1929,8 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingDa &mOutputType, &mIsSpatialized, &mIsBitPerfect)); } -TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, NonMmapPlaybackStreamMatchingDapMixSucceeds) { +TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, + NonMmapPlaybackStreamMatchingLoopbackDapMixSucceeds) { // Add mix matching the test uid. const int testUid = 12345; const auto param = GetParam(); @@ -1946,15 +1947,30 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, NonMmapPlaybackStreamMatchin &mOutputType, &mIsSpatialized, &mIsBitPerfect)); } +TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting, + MmapPlaybackStreamMatchingRenderDapMixSucceeds) { + // Add render-only mix matching the test uid. + const int testUid = 12345; + status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER, + /*mixAddress=*/"", audioConfig, {createUidCriterion(testUid)}); + ASSERT_EQ(NO_ERROR, ret); + + // Geting output for matching uid should succeed for mmaped stream. + audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_MMAP_NOIRQ; + ASSERT_EQ(NO_ERROR, + mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream, + createAttributionSourceState(testUid), &audioConfig, + &outputFlags, &mSelectedDeviceId, &mPortId, {}, + &mOutputType, &mIsSpatialized, &mIsBitPerfect)); +} + INSTANTIATE_TEST_SUITE_P( MmapPlaybackRerouting, AudioPolicyManagerTestMMapPlaybackRerouting, testing::Values(DPMmapTestParam(MIX_ROUTE_FLAG_LOOP_BACK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX, /*deviceAddress=*/"remote_submix_media"), DPMmapTestParam(MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER, AUDIO_DEVICE_OUT_REMOTE_SUBMIX, - /*deviceAddress=*/"remote_submix_media"), - DPMmapTestParam(MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER, - /*deviceAddress=*/""))); + /*deviceAddress=*/"remote_submix_media"))); class AudioPolicyManagerTestDPMixRecordInjection : public AudioPolicyManagerTestDynamicPolicy, public testing::WithParamInterface { From 90b4808e375a5bebcfaf4ef1df6ef3b18f53bd1c Mon Sep 17 00:00:00 2001 From: Ray Essick Date: Mon, 12 Jun 2023 11:11:51 -0500 Subject: [PATCH 020/148] Break cyclic binder dependency Break a cyclic binder dependency by having media.extractor perform datasource->close() on a separate thread. Bug: 199822700 Test: Boot, populate device Test: OEM verified against their tests / reproduction cases (cherry picked from https://android-review.googlesource.com/q/commit:b3d329c201b7be3fdbaac54d59cc2d626fe54b82) Merged-In: I981b9230589677cc559af4cc89c1e3643ea215f7 Change-Id: I981b9230589677cc559af4cc89c1e3643ea215f7 --- media/libstagefright/RemoteMediaExtractor.cpp | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp index baa2ca1208..574fc1a9c2 100644 --- a/media/libstagefright/RemoteMediaExtractor.cpp +++ b/media/libstagefright/RemoteMediaExtractor.cpp @@ -16,9 +16,16 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "RemoteMediaExtractor" + +#include +#include +#include +#include + #include #include +#include #include #include #include @@ -90,10 +97,65 @@ RemoteMediaExtractor::RemoteMediaExtractor( } } +static pthread_t myThread; +static std::list> pending; +static std::mutex pending_mutex; +static std::condition_variable pending_added; + +static void* closing_thread_func(void *arg) { + while (true) { + sp ds = nullptr; + std::unique_lock _lk(pending_mutex); + pending_added.wait(_lk, []{return !pending.empty();}); + ALOGV("worker thread wake up with %zu entries", pending.size()); + if (!pending.empty()) { + ds = pending.front(); + (void) pending.pop_front(); + } + _lk.unlock(); // unique_lock is not scoped + if (ds != nullptr) { + ds->close(); + } + } + + ALOGE("[unexpected] worker thread quit"); + return arg; +} + +// this can be '&ds' as long as the pending.push_back() bumps the +// reference counts to ensure the object lives long enough +static void start_close_thread(sp &ds) { + + // make sure we have our (single) worker thread + static std::once_flag sCheckOnce; + std::call_once(sCheckOnce, [&](){ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + pthread_create(&myThread, &attr, closing_thread_func, nullptr); + pthread_attr_destroy(&attr); + }); + + { + std::lock_guard _lm(pending_mutex); // scoped, no explicit unlock + pending.push_back(ds); + } + pending_added.notify_one(); // get the worker thread going +} + RemoteMediaExtractor::~RemoteMediaExtractor() { delete mExtractor; - mSource->close(); - mSource.clear(); + // TODO(287851984) hook for changing behavior this dynamically, drop after testing + int8_t new_scheme = property_get_bool("debug.mediaextractor.delayedclose", 1); + if (new_scheme != 0) { + ALOGV("deferred close()"); + start_close_thread(mSource); + mSource.clear(); + } else { + ALOGV("immediate close()"); + mSource->close(); + mSource.clear(); + } mExtractorPlugin = nullptr; // log the current record, provided it has some information worth recording if (MEDIA_LOG) { From 56074e3c0c6944a02b093dd2da51fab162210b07 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 8 Jun 2023 17:17:22 +0000 Subject: [PATCH 021/148] Fix lvm process copy length Bug: 271500140 Test: Test with YoutubeMusic with EQ enabled on both HIDL and AIDL Change-Id: I1f6d45231772a63024f250dc7525d78e82e13913 (cherry picked from commit d72a68685e6f851c5c5009dbf679e427a872e13f) Merged-In: I1f6d45231772a63024f250dc7525d78e82e13913 --- media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp index 4eea04f9d8..bfc50598ea 100644 --- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp +++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp @@ -166,9 +166,9 @@ LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance, const LVM_FLOAT* pInData * Bypass mode or everything off, so copy the input to the output */ if (pToProcess != pProcessed) { - Copy_Float(pToProcess, /* Source */ - pProcessed, /* Destination */ - (LVM_INT16)(NrChannels * NrFrames)); /* Copy all samples */ + Copy_Float(pToProcess, /* Source */ + pProcessed, /* Destination */ + SampleCount); /* Copy all samples */ } /* From d0e7d1e4ca0ef4d083e6098ee8518db166f15679 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 24 May 2023 05:49:43 +0000 Subject: [PATCH 022/148] Return correct value for virtualizer speaker angle getter Bug: 271500140 Test: Enable AIDL and flash to pixel, call `dumpsys media.audio_flinger` Change-Id: Ia7b57ed51a5aaba8b4f4bd2108a197f73926180f Merged-In: Ia7b57ed51a5aaba8b4f4bd2108a197f73926180f (cherry picked from commit 55e99fbace4a3226eda2f48923f7efe00871e4e2) --- media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp index cd9fb604d7..6d6403c679 100644 --- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp @@ -384,6 +384,7 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterVirtualizer(const Virtualizer:: if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) { auto angles = mContext->getSpeakerAngles(id.get()); + RETURN_IF(angles.size() == 0, EX_ILLEGAL_ARGUMENT, "getSpeakerAnglesFailed"); Virtualizer param = Virtualizer::make(angles); specific->set(param); return ndk::ScopedAStatus::ok(); From 9a0d5e016155c8be8b0d474d26602bf89914fc14 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 24 May 2023 06:11:45 +0000 Subject: [PATCH 023/148] Implement VolToDb with audio_utils_power_from_amplitude Bug: 271500140 Test: Enable AIDL and flash to pixel, call `dumpsys media.audio_flinger` Test: Play Youtube Music with effects on/off Change-Id: I0fb3fe24892d79b968f6bbde38bd8f78fbaa8d88 Merged-In: I0fb3fe24892d79b968f6bbde38bd8f78fbaa8d88 (cherry picked from commit 1c94524f2c7c38bbd362d2b803be4f931d39ec75) --- .../lvm/wrapper/Aidl/BundleContext.cpp | 35 +++++++++---------- .../lvm/wrapper/Aidl/BundleContext.h | 10 +++--- .../lvm/wrapper/Aidl/EffectBundleAidl.cpp | 2 +- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp index d026e2b672..b42c2f9397 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "BundleContext" #include +#include #include #include "BundleContext.h" @@ -397,15 +398,10 @@ LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const { return db_fix; } -// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude -int16_t BundleContext::VolToDb(uint32_t vol) const { - int16_t dB; - - dB = LVC_ToDB_s32Tos16(vol << 7); - dB = (dB + 8) >> 4; - dB = (dB < -96) ? -96 : dB; - - return dB; +/* static */ +float BundleContext::VolToDb(float vol) { + float dB = audio_utils_power_from_amplitude(vol); + return std::max(dB, -96.f); } RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { @@ -413,11 +409,12 @@ RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { LVM_ReturnStatus_en status = LVM_SUCCESS; // Convert volume to dB - int leftdB = VolToDb(volume.left); - int rightdB = VolToDb(volume.right); - int maxdB = std::max(leftdB, rightdB); - int pandB = rightdB - leftdB; - setVolumeLevel(maxdB * 100); + float leftdB = VolToDb(volume.left); + float rightdB = VolToDb(volume.right); + + float maxdB = std::max(leftdB, rightdB); + float pandB = rightdB - leftdB; + setVolumeLevel(maxdB); LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB; { @@ -551,18 +548,18 @@ RetCode BundleContext::setBassBoostStrength(int strength) { return limitLevel(); } -RetCode BundleContext::setVolumeLevel(int level) { +RetCode BundleContext::setVolumeLevel(float level) { if (mMuteEnabled) { - mLevelSaved = level / 100; + mLevelSaved = level; } else { - mVolume = level / 100; + mVolume = level; } LOG(INFO) << __func__ << " success with level " << level; return limitLevel(); } -int BundleContext::getVolumeLevel() const { - return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100); +float BundleContext::getVolumeLevel() const { + return (mMuteEnabled ? mLevelSaved : mVolume); } RetCode BundleContext::setVolumeMute(bool mute) { diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h index 47d5e5a66c..072296e552 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h @@ -80,8 +80,8 @@ class BundleContext final : public EffectContext { RetCode setBassBoostStrength(int strength); int getBassBoostStrength() const { return mBassStrengthSaved; } - RetCode setVolumeLevel(int level); - int getVolumeLevel() const; + RetCode setVolumeLevel(float level); + float getVolumeLevel() const; RetCode setVolumeMute(bool mute); int getVolumeMute() const { return mMuteEnabled; } @@ -141,14 +141,14 @@ class BundleContext final : public EffectContext { bool mVirtualizerTempDisabled = false; ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice; // Volume - int mLevelSaved = 0; /* for when mute is set, level must be saved */ - int mVolume = 0; + float mLevelSaved = 0; /* for when mute is set, level must be saved */ + float mVolume = 0; bool mMuteEnabled = false; /* Must store as mute = -96dB level */ void initControlParameter(LVM_ControlParams_t& params) const; void initHeadroomParameter(LVM_HeadroomParams_t& params) const; RetCode limitLevel(); - int16_t VolToDb(uint32_t vol) const; + static float VolToDb(float vol); LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const; RetCode updateControlParameter(const std::vector& bandLevels); bool isBandLevelIndexInRange(const std::vector& bandLevels) const; diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp index cd9fb604d7..c2d5cbf68b 100644 --- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp @@ -355,7 +355,7 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id, auto tag = id.get(); switch (tag) { case Volume::levelDb: { - volParam.set(mContext->getVolumeLevel()); + volParam.set(static_cast(mContext->getVolumeLevel())); break; } case Volume::mute: { From 27c1d59d5636359c1faa49b500b57d704f266d94 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 24 May 2023 01:40:02 +0000 Subject: [PATCH 024/148] Ignore EQ level range if no capability defined by effect implementation Fix lvm AIDL EQ gain db setting/getting Bug: 271500140 Test: Enable AIDL and flash to pixel Test: Play Youtube music with effect on/off Change-Id: I0726c8f35a6b40640bfa06c42baf736a268bd6f3 Merged-In: I0726c8f35a6b40640bfa06c42baf736a268bd6f3 (cherry picked from commit 19e8958c8219d8d0e95e41a8452e6850f2e76b3b) --- .../effectsAidlConversion/AidlConversionEq.cpp | 3 +++ .../libeffects/lvm/wrapper/Aidl/BundleContext.cpp | 14 ++++++++------ media/libeffects/lvm/wrapper/Aidl/BundleTypes.h | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp index 45b98a1395..fc867c7270 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp @@ -161,6 +161,9 @@ status_t AidlConversionEq::getParameter(EffectParamWriter& param) { return param.writeToValue(&bands); } case EQ_PARAM_LEVEL_RANGE: { + if (mDesc.capability.range.getTag() != Range::equalizer) { + return OK; + } const auto& ranges = mDesc.capability.range.get(); for (const auto& r : ranges) { if (r.min.getTag() == Equalizer::bandLevels && diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp index d026e2b672..05b849e91d 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp @@ -15,6 +15,7 @@ */ #include +#include #define LOG_TAG "BundleContext" #include @@ -441,8 +442,8 @@ RetCode BundleContext::setEqualizerPreset(const std::size_t presetIdx) { std::vector bandLevels; bandLevels.reserve(lvm::MAX_NUM_BANDS); for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) { - bandLevels.emplace_back( - Equalizer::BandLevel{static_cast(i), lvm::kSoftPresets[presetIdx][i]}); + bandLevels.emplace_back(Equalizer::BandLevel{static_cast(i), + lvm::kSoftPresets[presetIdx][i] * 100}); } RetCode ret = updateControlParameter(bandLevels); @@ -472,7 +473,8 @@ std::vector BundleContext::getEqualizerBandLevels() const std::vector bandLevels; bandLevels.reserve(lvm::MAX_NUM_BANDS); for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) { - bandLevels.emplace_back(Equalizer::BandLevel{static_cast(i), mBandGaindB[i]}); + bandLevels.emplace_back( + Equalizer::BandLevel{static_cast(i), mBandGaindB[i] * 100}); } return bandLevels; } @@ -506,9 +508,9 @@ RetCode BundleContext::updateControlParameter(const std::vector tempLevel; + std::array tempLevel(mBandGaindB); for (const auto& it : bandLevels) { - tempLevel[it.index] = it.levelMb; + tempLevel[it.index] = it.levelMb > 0 ? (it.levelMb + 50) / 100 : (it.levelMb - 50) / 100; } LVM_ControlParams_t params; @@ -527,7 +529,7 @@ RetCode BundleContext::updateControlParameter(const std::vector kEqRanges = { MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1), MAKE_RANGE(Equalizer, bandLevels, std::vector{ - Equalizer::BandLevel({.index = 0, .levelMb = -15})}, + Equalizer::BandLevel({.index = 0, .levelMb = -1500})}, std::vector{ - Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 15})}), + Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 1500})}), /* capability definition */ MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency), MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets), From 3a018579955277c8f96dc2d88b5d8736d9f34822 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 24 May 2023 00:45:43 +0000 Subject: [PATCH 025/148] Add isProxy in effect AIDL conversion helper constructor Bug: 271500140 Test: Enable AIDL and flash to pixel Test: Play Youtube music with effect on/off Change-Id: I1149f37faaba8a753baac49e6a04d978b1206a63 Merged-In: I1149f37faaba8a753baac49e6a04d978b1206a63 (cherry picked from commit a53ad3b487d4a7acd7ea02a0d7a2497ebc9dfee1) --- .../impl/EffectConversionHelperAidl.cpp | 5 +- .../impl/EffectConversionHelperAidl.h | 2 +- media/libaudiohal/impl/EffectHalAidl.cpp | 46 +++++++++---------- .../effectsAidlConversion/AidlConversionAec.h | 5 +- .../AidlConversionAgc1.h | 5 +- .../AidlConversionAgc2.h | 5 +- .../AidlConversionBassBoost.h | 4 +- .../AidlConversionDownmix.h | 5 +- .../AidlConversionDynamicsProcessing.h | 5 +- .../AidlConversionEnvReverb.h | 4 +- .../effectsAidlConversion/AidlConversionEq.h | 7 +-- .../AidlConversionHapticGenerator.h | 4 +- .../AidlConversionLoudnessEnhancer.h | 4 +- .../AidlConversionNoiseSuppression.h | 4 +- .../AidlConversionPresetReverb.h | 4 +- .../AidlConversionSpatializer.h | 4 +- .../AidlConversionVendorExtension.h | 4 +- .../AidlConversionVirtualizer.h | 4 +- .../AidlConversionVisualizer.h | 4 +- 19 files changed, 65 insertions(+), 60 deletions(-) diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp index 52fed917dc..63bba24791 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp @@ -72,14 +72,13 @@ const std::map effect, - int32_t sessionId, int32_t ioId, const Descriptor& desc) + int32_t sessionId, int32_t ioId, const Descriptor& desc, bool isProxy) : mSessionId(sessionId), mIoId(ioId), mDesc(desc), mEffect(std::move(effect)), mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC), - mIsProxyEffect(mDesc.common.id.proxy.has_value() && - mDesc.common.id.proxy.value() == mDesc.common.id.uuid) { + mIsProxyEffect(isProxy) { mCommon.session = sessionId; mCommon.ioHandle = ioId; mCommon.input = mCommon.output = kDefaultAudioConfig; diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h index 0c682ff348..e2cf87f114 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.h +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h @@ -54,7 +54,7 @@ class EffectConversionHelperAidl { EffectConversionHelperAidl( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc); + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxy); status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize, void* pReplyData); diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp index b9d9541f4e..561ebb9849 100644 --- a/media/libaudiohal/impl/EffectHalAidl.cpp +++ b/media/libaudiohal/impl/EffectHalAidl.cpp @@ -88,64 +88,64 @@ status_t EffectHalAidl::createAidlConversion( ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str()); if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) { - mConversion = - std::make_unique(effect, sessionId, ioId, desc); + mConversion = std::make_unique(effect, sessionId, ioId, + desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect:: getEffectTypeUuidAutomaticGainControlV1()) { mConversion = std::make_unique(effect, sessionId, ioId, - desc); + desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect:: getEffectTypeUuidAutomaticGainControlV2()) { mConversion = std::make_unique(effect, sessionId, ioId, - desc); + desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) { - mConversion = std::make_unique(effect, sessionId, - ioId, desc); + mConversion = std::make_unique( + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) { - mConversion = std::make_unique(effect, sessionId, - ioId, desc); + mConversion = std::make_unique( + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) { - mConversion = - std::make_unique(effect, sessionId, ioId, desc); + mConversion = std::make_unique(effect, sessionId, ioId, + desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) { - mConversion = std::make_unique(effect, sessionId, - ioId, desc); + mConversion = std::make_unique( + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) { - mConversion = - std::make_unique(effect, sessionId, ioId, desc); + mConversion = std::make_unique(effect, sessionId, ioId, + desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) { mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) { mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) { mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) { mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) { mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) { mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) { - mConversion = std::make_unique(effect, sessionId, - ioId, desc); + mConversion = std::make_unique( + effect, sessionId, ioId, desc, mIsProxyEffect); } else { // For unknown UUID, use vendor extension implementation mConversion = std::make_unique( - effect, sessionId, ioId, desc); + effect, sessionId, ioId, desc, mIsProxyEffect); } return OK; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h index 3ee419a581..61dd36a308 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h @@ -26,8 +26,9 @@ class AidlConversionAec : public EffectConversionHelperAidl { public: AidlConversionAec(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, + bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionAec() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h index b0509fd006..364b4736b3 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h @@ -26,8 +26,9 @@ class AidlConversionAgc1 : public EffectConversionHelperAidl { public: AidlConversionAgc1(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, + bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionAgc1() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h index 8f7eac75da..df9a9ec516 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h @@ -26,8 +26,9 @@ class AidlConversionAgc2 : public EffectConversionHelperAidl { public: AidlConversionAgc2(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, + bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionAgc2() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h index 9664aa1e17..424b837e15 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h @@ -27,8 +27,8 @@ class AidlConversionBassBoost : public EffectConversionHelperAidl { AidlConversionBassBoost( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionBassBoost() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h index 8b28ca3e37..f963f666da 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h @@ -26,8 +26,9 @@ class AidlConversionDownmix : public EffectConversionHelperAidl { public: AidlConversionDownmix(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, + bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionDownmix() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h index c5d5a54e39..62714c3feb 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h @@ -26,8 +26,9 @@ class AidlConversionDp : public EffectConversionHelperAidl { public: AidlConversionDp(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, + bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionDp() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h index 8b923744e2..95042eb67f 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h @@ -27,8 +27,8 @@ class AidlConversionEnvReverb : public EffectConversionHelperAidl { AidlConversionEnvReverb( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionEnvReverb() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h index f94556c1a2..53566e2c91 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h @@ -25,9 +25,10 @@ namespace effect { class AidlConversionEq : public EffectConversionHelperAidl { public: AidlConversionEq(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, - int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + int32_t sessionId, int32_t ioId, + const ::aidl::android::hardware::audio::effect::Descriptor& desc, + bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionEq() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h index 03114a526c..9890bfb3ae 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h @@ -27,8 +27,8 @@ class AidlConversionHapticGenerator : public EffectConversionHelperAidl { AidlConversionHapticGenerator( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionHapticGenerator() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h index c0402f948e..2ce14a65ba 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h @@ -27,8 +27,8 @@ class AidlConversionLoudnessEnhancer : public EffectConversionHelperAidl { AidlConversionLoudnessEnhancer( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionLoudnessEnhancer() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h index f51e13a316..fac121d757 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h @@ -27,8 +27,8 @@ class AidlConversionNoiseSuppression : public EffectConversionHelperAidl { AidlConversionNoiseSuppression( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionNoiseSuppression() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h index 397d6e6526..b975d72956 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h @@ -27,8 +27,8 @@ class AidlConversionPresetReverb : public EffectConversionHelperAidl { AidlConversionPresetReverb( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionPresetReverb() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h index c44567c510..7c60b14694 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h @@ -27,8 +27,8 @@ class AidlConversionSpatializer : public EffectConversionHelperAidl { AidlConversionSpatializer( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionSpatializer() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h index fd22e5cf47..16bfeba0ec 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h @@ -27,8 +27,8 @@ class AidlConversionVendorExtension : public EffectConversionHelperAidl { AidlConversionVendorExtension( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionVendorExtension() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h index 91c0fcd4d7..359d884caa 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h @@ -27,8 +27,8 @@ class AidlConversionVirtualizer : public EffectConversionHelperAidl { AidlConversionVirtualizer( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionVirtualizer() {} private: diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h index e380bc6b17..bc9320f3ff 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h @@ -27,8 +27,8 @@ class AidlConversionVisualizer : public EffectConversionHelperAidl { AidlConversionVisualizer( std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect, int32_t sessionId, int32_t ioId, - const ::aidl::android::hardware::audio::effect::Descriptor& desc) - : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {} + const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect) + : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {} ~AidlConversionVisualizer() {} private: From 4eef02fe239ea5d7e2b98f0a99dc70189bcd8c78 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 24 May 2023 00:34:53 +0000 Subject: [PATCH 026/148] Write unity gain back with successful EFFECT_CMD_SET_VOLUME handling Bug: 271500140 Test: Enable AIDL and flash to pixel Test: Play Youtube music with effect on/off Change-Id: I7e37a289f9c5f7773e500e59220963d1d17b5fb2 Merged-In: I7e37a289f9c5f7773e500e59220963d1d17b5fb2 (cherry picked from commit 1cd7cb9e3f6b84aa5d1f7d1a77704dbbdc912c4d) --- .../impl/EffectConversionHelperAidl.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp index 63bba24791..4c58fe94dc 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp @@ -318,17 +318,25 @@ status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const voi mEffect->setParameter(Parameter::make(aidlDevices)))); return *static_cast(pReplyData) = OK; } + status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData, - uint32_t* replySize __unused, - void* pReplyData __unused) { + uint32_t* replySize, void* pReplyData) { if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData) { ALOGE("%s parameter invalid %u %p", __func__, cmdSize, pCmdData); return BAD_VALUE; } - Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24), - .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)}; + + constexpr uint32_t unityGain = 1 << 24; + Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / unityGain, + .right = (float)(*(uint32_t*)pCmdData + 1) / unityGain}; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( mEffect->setParameter(Parameter::make(volume)))); + + // write unity gain back if volume was successfully set + if (replySize && *replySize == 2 * sizeof(uint32_t) && pReplyData) { + constexpr uint32_t vol_ret[2] = {unityGain, unityGain}; + memcpy(pReplyData, vol_ret, sizeof(vol_ret)); + } return OK; } From dce4376f3324164afadb12b1efdf71a6fd56b49d Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 17 May 2023 00:52:54 +0000 Subject: [PATCH 027/148] Use hexadecimal toString for AudioUuid Bug: 283012471 Test: Flash to Pixel device and check log Change-Id: Ia61e8caadab38226feb4c49bd92bb5b83026e80b Merged-In: Ia61e8caadab38226feb4c49bd92bb5b83026e80b --- media/libaudiohal/impl/EffectProxy.cpp | 24 ++++++++++--------- .../impl/EffectsFactoryHalAidl.cpp | 12 ++++++---- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index b61532dbb4..3bb045b454 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -20,6 +20,7 @@ //#define LOG_NDEBUG 0 #include +#include #include #include "EffectProxy.h" @@ -32,6 +33,7 @@ using ::aidl::android::hardware::audio::effect::IFactory; 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 @@ EffectProxy::~EffectProxy() { // 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::addSubEffect(const Descriptor& sub) { } 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(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::create() { } 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& effect) { ndk::ScopedAStatus status = mFactory->destroyEffect(effect); if (status.isOk()) { @@ -131,7 +133,7 @@ ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* of const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) { const auto& desc = std::get(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 @@ ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* of 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(itor->second).common.flags.toString().c_str()); return ndk::ScopedAStatus::ok(); } @@ -152,14 +154,14 @@ ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* of ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common, const std::optional& 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(sub.second); auto& openRet = std::get(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::open(const Parameter::Common& common, } 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& effect) { return effect->close(); }); @@ -203,7 +205,7 @@ ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) { // 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& effect) -> ndk::ScopedAStatus { diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp index 7ff74df42d..8fea3c30a9 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "EffectBufferHalAidl.h" @@ -43,6 +44,7 @@ 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; @@ -188,7 +190,7 @@ status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t 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; @@ -237,10 +239,10 @@ status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid(const AudioUuid& uu 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)); @@ -259,10 +261,10 @@ status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid( 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>( From e8eff23f8e83ab9624d6ad1cfec1e46dffecae87 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Wed, 3 May 2023 23:54:43 +0000 Subject: [PATCH 028/148] Refine EffectProxy logic To allow create multiple EffectProxy instances for same type Implement dump with all sub-effects Bug: 271500140 Test: Enable AIDL and flash to pixel Test: Play Youtube music with effect on/off Test: dumpsys media.audio_flinger Change-Id: I468d7e8712d7b098d869f147a4b40881ef11cabb Merged-In: I468d7e8712d7b098d869f147a4b40881ef11cabb --- .../impl/EffectConversionHelperAidl.cpp | 39 ++- .../impl/EffectConversionHelperAidl.h | 1 + media/libaudiohal/impl/EffectHalAidl.cpp | 12 +- media/libaudiohal/impl/EffectProxy.cpp | 260 +++++++++--------- media/libaudiohal/impl/EffectProxy.h | 103 ++++--- .../impl/EffectsFactoryHalAidl.cpp | 47 ++-- .../libaudiohal/impl/EffectsFactoryHalAidl.h | 15 +- media/libaudiohal/tests/EffectProxy_test.cpp | 90 +----- 8 files changed, 277 insertions(+), 290 deletions(-) diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp index 4c58fe94dc..72aa7d86e6 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -194,11 +195,9 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn))); if (mIsProxyEffect) { - const auto& ret = - std::static_pointer_cast(mEffect)->getEffectReturnParam(); - mStatusQ = std::make_shared(ret->statusMQ); - mInputQ = std::make_shared(ret->inputDataMQ); - mOutputQ = std::make_shared(ret->outputDataMQ); + mStatusQ = std::static_pointer_cast(mEffect)->getStatusMQ(); + mInputQ = std::static_pointer_cast(mEffect)->getInputMQ(); + mOutputQ = std::static_pointer_cast(mEffect)->getOutputMQ(); } else { mStatusQ = std::make_shared(openReturn.statusMQ); mInputQ = std::make_shared(openReturn.inputDataMQ); @@ -206,6 +205,7 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi } if (status_t status = updateEventFlags(); status != OK) { + ALOGV("%s closing at status %d", __func__, status); mEffect->close(); return status; } @@ -353,14 +353,15 @@ status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const vo ALOGI("%s offload param offload %s ioHandle %d", __func__, offload->isOffload ? "true" : "false", offload->ioHandle); mCommon.ioHandle = offload->ioHandle; - RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( - std::static_pointer_cast(mEffect)->setOffloadParam(offload))); - // update FMQs - const auto& ret = std::static_pointer_cast(mEffect)->getEffectReturnParam(); - mStatusQ = std::make_shared(ret->statusMQ); - mInputQ = std::make_shared(ret->inputDataMQ); - mOutputQ = std::make_shared(ret->outputDataMQ); - RETURN_STATUS_IF_ERROR(updateEventFlags()); + const auto& effectProxy = std::static_pointer_cast(mEffect); + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(effectProxy->setOffloadParam(offload))); + // update FMQs if the effect instance already open + if (State state; effectProxy->getState(&state).isOk() && state != State::INIT) { + mStatusQ = effectProxy->getStatusMQ(); + mInputQ = effectProxy->getInputMQ(); + mOutputQ = effectProxy->getOutputMQ(); + updateEventFlags(); + } } return *static_cast(pReplyData) = OK; } @@ -408,17 +409,27 @@ status_t EffectConversionHelperAidl::handleVisualizerMeasure(uint32_t cmdSize __ status_t EffectConversionHelperAidl::updateEventFlags() { status_t status = BAD_VALUE; EventFlag* efGroup = nullptr; - if (mStatusQ->isValid()) { + if (mStatusQ && mStatusQ->isValid()) { status = EventFlag::createEventFlag(mStatusQ->getEventFlagWord(), &efGroup); if (status != OK || !efGroup) { ALOGE("%s: create EventFlagGroup failed, ret %d, egGroup %p", __func__, status, efGroup); status = (status == OK) ? BAD_VALUE : status; } + } else if (isBypassing()) { + // for effect with bypass (no processing) flag, it's okay to not have statusQ + return OK; } + mEfGroup.reset(efGroup, EventFlagDeleter()); return status; } +bool EffectConversionHelperAidl::isBypassing() const { + return mEffect && + (mDesc.common.flags.bypass || + (mIsProxyEffect && std::static_pointer_cast(mEffect)->isBypassing())); +} + } // namespace effect } // namespace android diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h index e2cf87f114..7c8f11b481 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.h +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h @@ -41,6 +41,7 @@ class EffectConversionHelperAidl { std::shared_ptr getInputMQ() { return mInputQ; } std::shared_ptr getOutputMQ() { return mOutputQ; } std::shared_ptr getEventFlagGroup() { return mEfGroup; } + bool isBypassing() const; protected: const int32_t mSessionId; diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp index 561ebb9849..e4c330970c 100644 --- a/media/libaudiohal/impl/EffectHalAidl.cpp +++ b/media/libaudiohal/impl/EffectHalAidl.cpp @@ -74,9 +74,12 @@ EffectHalAidl::EffectHalAidl(const std::shared_ptr& factory, } EffectHalAidl::~EffectHalAidl() { - if (mEffect) { - mIsProxyEffect ? std::static_pointer_cast(mEffect)->destroy() - : mFactory->destroyEffect(mEffect); + if (mFactory && mEffect) { + if (mIsProxyEffect) { + std::static_pointer_cast(mEffect)->destroy(); + } else { + mFactory->destroyEffect(mEffect); + } } } @@ -166,6 +169,9 @@ status_t EffectHalAidl::process() { auto inputQ = mConversion->getInputMQ(); auto outputQ = mConversion->getOutputMQ(); auto efGroup = mConversion->getEventFlagGroup(); + if (mConversion->isBypassing()) { + return OK; + } if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ || !outputQ->isValid() || !efGroup) { ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__, diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index 3bb045b454..f83d47998c 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -15,9 +15,10 @@ */ #include +#include #include #define LOG_TAG "EffectProxy" -//#define LOG_NDEBUG 0 +// #define LOG_NDEBUG 0 #include #include @@ -25,6 +26,7 @@ #include "EffectProxy.h" +using ::aidl::android::hardware::audio::effect::Capability; using ::aidl::android::hardware::audio::effect::CommandId; using ::aidl::android::hardware::audio::effect::Descriptor; using ::aidl::android::hardware::audio::effect::Flags; @@ -33,19 +35,28 @@ using ::aidl::android::hardware::audio::effect::IFactory; 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 { - -EffectProxy::EffectProxy(const Descriptor::Identity& id, const std::shared_ptr& factory) - : mIdentity([](const Descriptor::Identity& subId) { - // update EffectProxy implementation UUID to the sub-effect proxy UUID - ALOG_ASSERT(subId.proxy.has_value(), "Sub-effect Identity must have valid proxy UUID"); - Descriptor::Identity tempId = subId; - tempId.uuid = subId.proxy.value(); - return tempId; - }(id)), + +namespace android::effect { + +EffectProxy::EffectProxy(const AudioUuid& uuid, const std::vector& descriptors, + const std::shared_ptr& factory) + : mDescriptorCommon(buildDescriptorCommon(uuid, descriptors)), + mSubEffects( + [](const std::vector& descs, const std::shared_ptr& factory) { + std::vector subEffects; + ALOG_ASSERT(factory, "invalid EffectFactory handle"); + ndk::ScopedAStatus status = ndk::ScopedAStatus::ok(); + for (const auto& desc : descs) { + SubEffect sub({.descriptor = desc}); + status = factory->createEffect(desc.common.id.uuid, &sub.handle); + if (!status.isOk() || !sub.handle) { + ALOGW("%s create sub-effect %s failed", __func__, + ::android::audio::utils::toString(desc.common.id.uuid).c_str()); + } + subEffects.emplace_back(sub); + } + return subEffects; + }(descriptors, factory)), mFactory(factory) {} EffectProxy::~EffectProxy() { @@ -54,68 +65,9 @@ EffectProxy::~EffectProxy() { mSubEffects.clear(); } -// 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__, 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()); - return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, - "illegalSubEffect"); - } - - // not create sub-effect yet - std::get(mSubEffects[sub.common.id]) = nullptr; - std::get(mSubEffects[sub.common.id]) = sub; - // set the last added sub-effect to active before setOffloadParam() - mActiveSub = sub.common.id; - ALOGI("%s add %s to proxy %s flag %s", __func__, mActiveSub.toString().c_str(), - mIdentity.toString().c_str(), sub.common.flags.toString().c_str()); - - if (sub.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) { - mSubFlags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL; - } - - // initial flag values before we know which sub-effect to active (with setOffloadParam) - // same as HIDL EffectProxy flags - mSubFlags.type = Flags::Type::INSERT; - mSubFlags.insert = Flags::Insert::LAST; - mSubFlags.volume = Flags::Volume::CTRL; - - // set indication if any sub-effect indication was set - mSubFlags.offloadIndication |= sub.common.flags.offloadIndication; - mSubFlags.deviceIndication |= sub.common.flags.deviceIndication; - mSubFlags.audioModeIndication |= sub.common.flags.audioModeIndication; - mSubFlags.audioSourceIndication |= sub.common.flags.audioSourceIndication; - - // set bypass when all sub-effects are bypassing - mSubFlags.bypass &= sub.common.flags.bypass; - return ndk::ScopedAStatus::ok(); -} - -ndk::ScopedAStatus EffectProxy::create() { - ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str()); - ndk::ScopedAStatus status = ndk::ScopedAStatus::ok(); - - for (auto& sub : mSubEffects) { - auto& effectHandle = std::get(sub.second); - 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__, toString(sub.first.uuid).c_str()); - break; - } - } - - // destroy all created effects if failure - if (!status.isOk()) { - destroy(); - } - return status; -} - ndk::ScopedAStatus EffectProxy::destroy() { - ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str()); + ALOGV("%s: %s", __func__, + ::android::audio::utils::toString(mDescriptorCommon.id.type).c_str()); return runWithAllSubEffects([&](std::shared_ptr& effect) { ndk::ScopedAStatus status = mFactory->destroyEffect(effect); if (status.isOk()) { @@ -125,28 +77,24 @@ ndk::ScopedAStatus EffectProxy::destroy() { }); } -const IEffect::OpenEffectReturn* EffectProxy::getEffectReturnParam() { - return &std::get(mSubEffects[mActiveSub]); -} - ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* offload) { const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) { - const auto& desc = std::get(sub.second); - ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload, - toString(desc.common.id.uuid).c_str(), desc.common.flags.toString().c_str()); + const auto& desc = sub.descriptor; return offload->isOffload == (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL); }); if (itor == mSubEffects.end()) { ALOGE("%s no %soffload sub-effect found", __func__, offload->isOffload ? "" : "non-"); + mActiveSubIdx = 0; return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "noActiveEffctFound"); } - mActiveSub = itor->first; - ALOGI("%s: active %soffload sub-effect: %s, flags %s", __func__, - offload->isOffload ? "" : "non-", toString(mActiveSub.uuid).c_str(), - std::get(itor->second).common.flags.toString().c_str()); + mActiveSubIdx = std::distance(mSubEffects.begin(), itor); + ALOGV("%s: active %soffload sub-effect %zu descriptor: %s", __func__, + offload->isOffload ? "" : "non-", mActiveSubIdx, + ::android::audio::utils::toString(mSubEffects[mActiveSubIdx].descriptor.common.id.uuid) + .c_str()); return ndk::ScopedAStatus::ok(); } @@ -154,20 +102,24 @@ ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* of ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common, const std::optional& specific, IEffect::OpenEffectReturn* ret __unused) { - 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(sub.second); - auto& openRet = std::get(sub.second); - if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) { - ALOGE("%s: failed to open UUID %s", __func__, toString(sub.first.uuid).c_str()); + IEffect::OpenEffectReturn openReturn; + if (!sub.handle || !(status = sub.handle->open(common, specific, &openReturn)).isOk()) { + ALOGE("%s: failed to open %p UUID %s", __func__, sub.handle.get(), + ::android::audio::utils::toString(sub.descriptor.common.id.uuid).c_str()); break; } + sub.effectMq.statusQ = std::make_shared(openReturn.statusMQ); + sub.effectMq.inputQ = std::make_shared(openReturn.inputDataMQ); + sub.effectMq.outputQ = std::make_shared(openReturn.outputDataMQ); } // close all opened effects if failure if (!status.isOk()) { + ALOGE("%s: closing all sub-effects with error %s", __func__, + status.getDescription().c_str()); close(); } @@ -175,38 +127,68 @@ ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common, } ndk::ScopedAStatus EffectProxy::close() { - ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str()); return runWithAllSubEffects([&](std::shared_ptr& effect) { return effect->close(); }); } ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) { + desc->common = mDescriptorCommon; + desc->capability = mSubEffects[mActiveSubIdx].descriptor.capability; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus EffectProxy::buildDescriptor(const AudioUuid& uuid, + const std::vector& subEffectDescs, + Descriptor* desc) { if (!desc) { - ALOGE("%s: nuull descriptor pointer", __func__); + ALOGE("%s: null descriptor pointer", __func__); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "nullptr"); } - auto& activeSubEffect = std::get(mSubEffects[mActiveSub]); - // return initial descriptor if no active sub-effect exist - if (!activeSubEffect) { - desc->common.id = mIdentity; - desc->common.flags = mSubFlags; - desc->common.name = "Proxy"; - desc->common.implementor = "AOSP"; - } else { - *desc = std::get(mSubEffects[mActiveSub]); - desc->common.id = mIdentity; + if (subEffectDescs.size() < 2) { + ALOGE("%s: proxy need at least 2 sub-effects, got %zu", __func__, subEffectDescs.size()); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "needMoreSubEffects"); } - ALOGI("%s with %s", __func__, desc->toString().c_str()); + desc->common = buildDescriptorCommon(uuid, subEffectDescs); return ndk::ScopedAStatus::ok(); } +Descriptor::Common EffectProxy::buildDescriptorCommon( + const AudioUuid& uuid, const std::vector& subEffectDescs) { + Descriptor::Common common; + for (const auto& desc : subEffectDescs) { + if (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) { + common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL; + } + + // initial flag values before we know which sub-effect to active (with setOffloadParam) + // same as HIDL EffectProxy flags + common.flags.type = Flags::Type::INSERT; + common.flags.insert = Flags::Insert::LAST; + common.flags.volume = Flags::Volume::CTRL; + + // set indication if any sub-effect indication was set + common.flags.offloadIndication |= desc.common.flags.offloadIndication; + common.flags.deviceIndication |= desc.common.flags.deviceIndication; + common.flags.audioModeIndication |= desc.common.flags.audioModeIndication; + common.flags.audioSourceIndication |= desc.common.flags.audioSourceIndication; + } + + // copy type UUID from any of sub-effects, all sub-effects should have same type + common.id.type = subEffectDescs[0].common.id.type; + // replace implementation UUID with proxy UUID. + common.id.uuid = uuid; + common.id.proxy = std::nullopt; + common.name = "Proxy"; + common.implementor = "AOSP"; + return common; +} + // 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__, toString(mIdentity.type).c_str(), - android::internal::ToString(id).c_str()); return runWithActiveSubEffectThenOthers( [&](const std::shared_ptr& effect) -> ndk::ScopedAStatus { return effect->command(id); @@ -241,34 +223,30 @@ ndk::ScopedAStatus EffectProxy::runWithActiveSubEffectThenOthers( std::function&)> const& func) { ndk::ScopedAStatus status = runWithActiveSubEffect(func); if (!status.isOk()) { - return status; + ALOGE("%s active sub-effect return error %s", __func__, status.getDescription().c_str()); } - // proceed with others if active sub-effect success - for (const auto& sub : mSubEffects) { - auto& effect = std::get(sub.second); - if (sub.first != mActiveSub) { - if (!effect) { - ALOGE("%s null sub-effect interface for %s", __func__, - sub.first.toString().c_str()); - continue; - } - func(effect); + // proceed with others + for (size_t i = 0; i < mSubEffects.size() && i != mActiveSubIdx; i++) { + if (!mSubEffects[i].handle) { + ALOGE("%s null sub-effect interface for %s", __func__, + mSubEffects[i].descriptor.common.id.uuid.toString().c_str()); + continue; } + func(mSubEffects[i].handle); } return status; } ndk::ScopedAStatus EffectProxy::runWithActiveSubEffect( std::function&)> const& func) { - auto& effect = std::get(mSubEffects[mActiveSub]); - if (!effect) { + if (!mSubEffects[mActiveSubIdx].handle) { ALOGE("%s null active sub-effect interface, active %s", __func__, - mActiveSub.toString().c_str()); + mSubEffects[mActiveSubIdx].descriptor.toString().c_str()); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "activeSubEffectNull"); } - return func(effect); + return func(mSubEffects[mActiveSubIdx].handle); } ndk::ScopedAStatus EffectProxy::runWithAllSubEffects( @@ -276,12 +254,11 @@ ndk::ScopedAStatus EffectProxy::runWithAllSubEffects( ndk::ScopedAStatus status = ndk::ScopedAStatus::ok(); // proceed with others if active sub-effect success for (auto& sub : mSubEffects) { - auto& effect = std::get(sub.second); - if (!effect) { - ALOGW("%s null sub-effect interface for %s", __func__, sub.first.toString().c_str()); + if (!sub.handle) { + ALOGW("%s null sub-effect interface %s", __func__, sub.descriptor.toString().c_str()); continue; } - ndk::ScopedAStatus temp = func(effect); + ndk::ScopedAStatus temp = func(sub.handle); if (!temp.isOk()) { status = ndk::ScopedAStatus::fromStatus(temp.getStatus()); } @@ -289,5 +266,34 @@ ndk::ScopedAStatus EffectProxy::runWithAllSubEffects( return status; } -} // namespace effect -} // namespace android +bool EffectProxy::isBypassing() const { + return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass; +} + +binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) { + const std::string dumpString = toString(); + write(fd, dumpString.c_str(), dumpString.size()); + + return runWithAllSubEffects([&](std::shared_ptr& effect) { + return ndk::ScopedAStatus::fromStatus(effect->dump(fd, args, numArgs)); + }) + .getStatus(); +} + +std::string EffectProxy::toString(size_t level) const { + std::string prefixSpace(level, ' '); + std::string ss = prefixSpace + "EffectProxy:\n"; + prefixSpace += " "; + base::StringAppendF(&ss, "%sDescriptorCommon: %s\n", prefixSpace.c_str(), + mDescriptorCommon.toString().c_str()); + base::StringAppendF(&ss, "%sActiveSubIdx: %zu\n", prefixSpace.c_str(), mActiveSubIdx); + base::StringAppendF(&ss, "%sAllSubEffects:\n", prefixSpace.c_str()); + for (size_t i = 0; i < mSubEffects.size(); i++) { + base::StringAppendF(&ss, "%s[%zu] - Handle: %p, %s\n", prefixSpace.c_str(), i, + mSubEffects[i].handle ? mSubEffects[i].handle.get() : nullptr, + mSubEffects[i].descriptor.toString().c_str()); + } + return ss; +} + +} // namespace android::effect diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h index ffb8a194d7..18e1567819 100644 --- a/media/libaudiohal/impl/EffectProxy.h +++ b/media/libaudiohal/impl/EffectProxy.h @@ -40,27 +40,10 @@ namespace effect { */ class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEffect { public: - EffectProxy(const ::aidl::android::hardware::audio::effect::Descriptor::Identity& id, - const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory); - - /** - * Add a sub effect into the proxy, the descriptor of candidate sub-effect need to have same - * proxy UUID as mUuid. - */ - ndk::ScopedAStatus addSubEffect( - const ::aidl::android::hardware::audio::effect::Descriptor& sub); - - /** - * Create all sub-effects via AIDL IFactory, always call create() after all sub-effects added - * successfully with addSubEffect. - */ - ndk::ScopedAStatus create(); - - /** - * Destroy all sub-effects via AIDL IFactory, always call create() after all sub-effects added - * successfully with addSubEffect. - */ - ndk::ScopedAStatus destroy(); + EffectProxy( + const ::aidl::android::media::audio::common::AudioUuid& uuid, + const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& descriptors, + const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory); /** * Handle offload parameter setting from framework. @@ -68,11 +51,9 @@ class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEff ndk::ScopedAStatus setOffloadParam(const effect_offload_param_t* offload); /** - * Get the const reference of the active sub-effect return parameters. - * Always use this interface to get the effect open return parameters (FMQs) after a success - * setOffloadParam() call. + * Destroy all sub-effects via AIDL IFactory. */ - const IEffect::OpenEffectReturn* getEffectReturnParam(); + ndk::ScopedAStatus destroy(); // IEffect interfaces override ndk::ScopedAStatus open( @@ -91,25 +72,59 @@ class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEff const ::aidl::android::hardware::audio::effect::Parameter::Id& id, ::aidl::android::hardware::audio::effect::Parameter* param) override; - private: - // Proxy identity, copy from one sub-effect, and update the implementation UUID to proxy UUID - const ::aidl::android::hardware::audio::effect::Descriptor::Identity mIdentity; - const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory; + static ndk::ScopedAStatus buildDescriptor( + const ::aidl::android::media::audio::common::AudioUuid& uuid, + const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& subEffectDescs, + ::aidl::android::hardware::audio::effect::Descriptor* desc); + + /** + * Get the const reference of the active sub-effect return parameters. + * Always use this interface to get the effect open return parameters (FMQs) after a success + * setOffloadParam() call. + */ + using StatusMQ = ::android::AidlMessageQueue< + ::aidl::android::hardware::audio::effect::IEffect::Status, + ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>; + using DataMQ = ::android::AidlMessageQueue< + float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>; + const std::shared_ptr& getStatusMQ() const { + return mSubEffects[mActiveSubIdx].effectMq.statusQ; + } + const std::shared_ptr& getInputMQ() const { + return mSubEffects[mActiveSubIdx].effectMq.inputQ; + } + const std::shared_ptr& getOutputMQ() const { + return mSubEffects[mActiveSubIdx].effectMq.outputQ; + } + + bool isBypassing() const; + + // call dump for all sub-effects + binder_status_t dump(int fd, const char** args, uint32_t numArgs) override; + + std::string toString(size_t indent = 0) const; - // A map of sub effects descriptor to the IEffect handle and return FMQ - enum SubEffectTupleIndex { HANDLE, DESCRIPTOR, RETURN }; - using EffectProxySub = - std::tuple, - ::aidl::android::hardware::audio::effect::Descriptor, - ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn>; - std::map - mSubEffects; + private: + // Proxy descriptor common part, copy from one sub-effect, and update the implementation UUID to + // proxy UUID, proxy descriptor capability part comes from the active sub-effect capability + const ::aidl::android::hardware::audio::effect::Descriptor::Common mDescriptorCommon; + + struct EffectMQ { + std::shared_ptr statusQ; + std::shared_ptr inputQ, outputQ; + }; + struct SubEffect { + const ::aidl::android::hardware::audio::effect::Descriptor descriptor; + std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> handle; + EffectMQ effectMq; + }; + std::vector mSubEffects; - // Descriptor of the only active effect in the mSubEffects map - ::aidl::android::hardware::audio::effect::Descriptor::Identity mActiveSub; + const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory; - // keep the flag of sub-effects - ::aidl::android::hardware::audio::effect::Flags mSubFlags; + // index of the active sub-effects, by default use the first one (index 0) + // It's safe to assume there will always at least two SubEffects in mSubEffects + size_t mActiveSubIdx = 0; ndk::ScopedAStatus runWithActiveSubEffectThenOthers( std::function&)> const& func); + // build Descriptor.Common with all sub-effect descriptors + static ::aidl::android::hardware::audio::effect::Descriptor::Common buildDescriptorCommon( + const ::aidl::android::media::audio::common::AudioUuid& uuid, + const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& + subEffectDescs); + // close and release all sub-effects ~EffectProxy(); }; diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp index 8fea3c30a9..1c5e4742c7 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp @@ -68,26 +68,28 @@ EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr effectsFa } return list; }()), - mUuidProxyMap([this]() { - std::map> proxyMap; - for (const auto& desc : mHalDescList) { - // create EffectProxy + mProxyUuidDescriptorMap([this]() { + std::map> proxyUuidMap; + for (auto& desc : mHalDescList) { if (desc.common.id.proxy.has_value()) { - const auto& uuid = desc.common.id.proxy.value(); - if (0 == proxyMap.count(uuid)) { - proxyMap.insert({uuid, ndk::SharedRefBase::make(desc.common.id, - mFactory)}); + auto& uuid = desc.common.id.proxy.value(); + if (proxyUuidMap.count(uuid) == 0) { + proxyUuidMap.insert({uuid, {desc}}); + } else { + proxyUuidMap[uuid].emplace_back(desc); } - proxyMap[uuid]->addSubEffect(desc); - ALOGI("%s addSubEffect %s", __func__, desc.common.toString().c_str()); } } - return proxyMap; + return proxyUuidMap; }()), mProxyDescList([this]() { std::vector list; - for (const auto& proxy : mUuidProxyMap) { - if (Descriptor desc; proxy.second && proxy.second->getDescriptor(&desc).isOk()) { + for (const auto& proxy : mProxyUuidDescriptorMap) { + if (Descriptor desc; + EffectProxy::buildDescriptor(proxy.first /* uuid */, + proxy.second /* sub-effect descriptor list */, + &desc /* proxy descriptor */) + .isOk()) { list.emplace_back(std::move(desc)); } } @@ -118,7 +120,8 @@ status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) { } *pNumEffects = mEffectCount; - ALOGI("%s %d", __func__, *pNumEffects); + ALOGD("%s %d non %zu proxyMap %zu proxyDesc %zu", __func__, *pNumEffects, + mNonProxyDescList.size(), mProxyUuidDescriptorMap.size(), mProxyDescList.size()); return OK; } @@ -183,8 +186,10 @@ status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t // Use EffectProxy interface instead of IFactory to create const bool isProxy = isProxyEffect(aidlUuid); if (isProxy) { - aidlEffect = mUuidProxyMap.at(aidlUuid); - RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mUuidProxyMap.at(aidlUuid)->create())); + aidlEffect = ndk::SharedRefBase::make( + aidlUuid, mProxyUuidDescriptorMap.at(aidlUuid) /* sub-effect descriptor list */, + mFactory); + mProxyList.emplace_back(std::static_pointer_cast(aidlEffect)); } else { RETURN_STATUS_IF_ERROR( statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect))); @@ -203,11 +208,9 @@ status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t status_t EffectsFactoryHalAidl::dumpEffects(int fd) { status_t ret = OK; // record the error ret and continue dump as many effects as possible - for (const auto& proxy : mUuidProxyMap) { - if (proxy.second) { - if (status_t temp = proxy.second->dump(fd, nullptr, 0); temp != OK) { - ret = temp; - } + for (const auto& proxy : mProxyList) { + if (status_t temp = BAD_VALUE; proxy && (temp = proxy->dump(fd, nullptr, 0)) != OK) { + ret = temp; } } RETURN_STATUS_IF_ERROR(mFactory->dump(fd, nullptr, 0)); @@ -273,7 +276,7 @@ status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid( } bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const { - return 0 != mUuidProxyMap.count(uuid); + return 0 != mProxyUuidDescriptorMap.count(uuid); } std::shared_ptr EffectsFactoryHalAidl::getProcessings() const { diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h index 9fae9d4671..73089b0088 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include @@ -71,10 +72,9 @@ class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface { const detail::AudioHalVersionInfo mHalVersion; // Full list of HAL effect descriptors const std::vector mHalDescList; - // Map of proxy UUID (key) to the proxy object - const std::map<::aidl::android::media::audio::common::AudioUuid /* proxy impl UUID */, - std::shared_ptr> - mUuidProxyMap; + // Map of proxy UUID (key) to the Descriptor of sub-effects + const std::map<::aidl::android::media::audio::common::AudioUuid, std::vector> + mProxyUuidDescriptorMap; // List of effect proxy, initialize after mUuidProxyMap because it need to have all sub-effects const std::vector mProxyDescList; // List of non-proxy effects @@ -84,13 +84,16 @@ class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface { // Query result of pre and post processing from effect factory const std::vector mAidlProcessings; + // list of the EffectProxy instances + std::list> mProxyList; + virtual ~EffectsFactoryHalAidl() = default; status_t getHalDescriptorWithImplUuid( - const aidl::android::media::audio::common::AudioUuid& uuid, + const ::aidl::android::media::audio::common::AudioUuid& uuid, effect_descriptor_t* pDescriptor); status_t getHalDescriptorWithTypeUuid( - const aidl::android::media::audio::common::AudioUuid& type, + const ::aidl::android::media::audio::common::AudioUuid& type, std::vector* descriptors); bool isProxyEffect(const aidl::android::media::audio::common::AudioUuid& uuid) const; diff --git a/media/libaudiohal/tests/EffectProxy_test.cpp b/media/libaudiohal/tests/EffectProxy_test.cpp index 92e3dce104..8668e85bcf 100644 --- a/media/libaudiohal/tests/EffectProxy_test.cpp +++ b/media/libaudiohal/tests/EffectProxy_test.cpp @@ -60,7 +60,7 @@ class EffectProxyTest : public testing::Test { mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &mDescs); for (const auto& desc : mDescs) { if (desc.common.id.proxy.has_value()) { - mProxyDescs.insert({desc.common.id, desc}); + mProxyDescs[desc.common.id.proxy.value()].emplace_back(desc); } } } @@ -96,44 +96,24 @@ class EffectProxyTest : public testing::Test { return common; } - static bool isFlagSet(const ::aidl::android::hardware::audio::effect::Descriptor& desc, - Flags::HardwareAccelerator flag) { - return desc.common.flags.hwAcceleratorMode == flag; - } - enum TupleIndex { HANDLE, DESCRIPTOR }; using EffectProxyTuple = std::tuple, std::vector>; std::map createAllProxies() { std::map proxyMap; for (const auto& itor : mProxyDescs) { - const auto& uuid = itor.first.proxy.value(); + const auto& uuid = itor.first; if (proxyMap.end() == proxyMap.find(uuid)) { std::get(proxyMap[uuid]) = - ndk::SharedRefBase::make(itor.first, mFactory); + ndk::SharedRefBase::make(itor.first, itor.second, mFactory); } } return proxyMap; } - bool addAllSubEffects(std::map proxyMap) { - for (auto& itor : mProxyDescs) { - const auto& uuid = itor.first.proxy.value(); - if (proxyMap.end() == proxyMap.find(uuid)) { - return false; - } - auto& proxy = std::get(proxyMap[uuid]); - if (!proxy->addSubEffect(itor.second).isOk()) { - return false; - } - std::get(proxyMap[uuid]).emplace_back(itor.second); - } - return true; - } - std::shared_ptr mFactory; std::vector mDescs; - std::map mProxyDescs; + std::map> mProxyDescs; }; TEST_F(EffectProxyTest, createProxy) { @@ -144,24 +124,20 @@ TEST_F(EffectProxyTest, createProxy) { TEST_F(EffectProxyTest, addSubEffectsCreateAndDestroy) { auto proxyMap = createAllProxies(); - ASSERT_TRUE(addAllSubEffects(proxyMap)); for (const auto& itor : proxyMap) { auto& proxy = std::get(itor.second); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->destroy().isOk()); } } TEST_F(EffectProxyTest, addSubEffectsCreateOpenCloseDestroy) { auto proxyMap = createAllProxies(); - EXPECT_TRUE(addAllSubEffects(proxyMap)); Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; for (const auto& itor : proxyMap) { auto& proxy = std::get(itor.second); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); EXPECT_TRUE(proxy->close().isOk()); EXPECT_TRUE(proxy->destroy().isOk()); @@ -171,33 +147,23 @@ TEST_F(EffectProxyTest, addSubEffectsCreateOpenCloseDestroy) { // Add sub-effects, set active sub-effect with different checkers TEST_F(EffectProxyTest, setOffloadParam) { auto proxyMap = createAllProxies(); - EXPECT_TRUE(addAllSubEffects(proxyMap)); // Any flag exist should be able to set successfully - bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false; - for (const auto& itor : mProxyDescs) { - isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE); - isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE); - isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL); - } - Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; for (const auto& itor : proxyMap) { auto& proxy = std::get(itor.second); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); effect_offload_param_t offloadParam{false, 0}; - EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); offloadParam.isOffload = true; - EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->close().isOk()); EXPECT_TRUE(proxy->destroy().isOk()); } } TEST_F(EffectProxyTest, destroyWithoutCreate) { auto proxyMap = createAllProxies(); - ASSERT_TRUE(addAllSubEffects(proxyMap)); for (const auto& itor : proxyMap) { auto& proxy = std::get(itor.second); @@ -207,11 +173,9 @@ TEST_F(EffectProxyTest, destroyWithoutCreate) { TEST_F(EffectProxyTest, closeWithoutOpen) { auto proxyMap = createAllProxies(); - ASSERT_TRUE(addAllSubEffects(proxyMap)); for (const auto& itor : proxyMap) { auto& proxy = std::get(itor.second); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->close().isOk()); EXPECT_TRUE(proxy->destroy().isOk()); @@ -221,16 +185,6 @@ TEST_F(EffectProxyTest, closeWithoutOpen) { // Add sub-effects, set active sub-effect, create, open, and send command, expect success handling TEST_F(EffectProxyTest, normalSequency) { auto proxyMap = createAllProxies(); - ASSERT_TRUE(addAllSubEffects(proxyMap)); - - bool isTunnelExist = [&]() { - for (const auto& itor : mProxyDescs) { - if (isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL)) { - return true; - } - } - return false; - }(); Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; @@ -242,14 +196,14 @@ TEST_F(EffectProxyTest, normalSequency) { Parameter expect; auto& proxy = std::get(itor.second); effect_offload_param_t offloadParam{true, 0}; - EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); EXPECT_TRUE(proxy->setParameter(param).isOk()); EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); - EXPECT_EQ(expect, param); + EXPECT_EQ(expect, param) << " EXPECTED: " << expect.toString() + << "\nACTUAL: " << param.toString(); EXPECT_TRUE(proxy->command(CommandId::START).isOk()); EXPECT_TRUE(proxy->getState(&state).isOk()); @@ -267,14 +221,6 @@ TEST_F(EffectProxyTest, normalSequency) { // setParameter, change active sub-effect, verify with getParameter TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) { auto proxyMap = createAllProxies(); - EXPECT_TRUE(addAllSubEffects(proxyMap)); - - bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false; - for (const auto& itor : mProxyDescs) { - isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE); - isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE); - isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL); - } Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; @@ -284,19 +230,18 @@ TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) { for (const auto& itor : proxyMap) { Parameter expect; auto& proxy = std::get(itor.second); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); EXPECT_TRUE(proxy->setParameter(param).isOk()); EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); EXPECT_EQ(expect, param); effect_offload_param_t offloadParam{false, 0}; - EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); EXPECT_EQ(expect, param); offloadParam.isOffload = true; - EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); EXPECT_EQ(expect, param); @@ -308,14 +253,6 @@ TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) { // send command, change active sub-effect, then verify the state with getState TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) { auto proxyMap = createAllProxies(); - ASSERT_TRUE(addAllSubEffects(proxyMap)); - - bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false; - for (const auto& itor : mProxyDescs) { - isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE); - isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE); - isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL); - } Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; @@ -323,7 +260,6 @@ TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) { for (const auto& itor : proxyMap) { Parameter expect; auto& proxy = std::get(itor.second); - EXPECT_TRUE(proxy->create().isOk()); EXPECT_TRUE(proxy->getState(&state).isOk()); EXPECT_EQ(State::INIT, state); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); @@ -334,12 +270,12 @@ TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) { EXPECT_EQ(State::PROCESSING, state); effect_offload_param_t offloadParam{false, 0}; - EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->getState(&state).isOk()); EXPECT_EQ(State::PROCESSING, state); offloadParam.isOffload = true; - EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk()); + EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->getState(&state).isOk()); EXPECT_EQ(State::PROCESSING, state); From 15cb280f6ff6f11f367b283641fae7b1e28ab105 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Mon, 5 Jun 2023 16:44:32 +0000 Subject: [PATCH 029/148] Keep the millibels precision for lvm EQ gain Bug: 285632900 Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit Change-Id: I1b3f5832a4357327721c45d3a91926e9aab25a04 Merged-In: I1b3f5832a4357327721c45d3a91926e9aab25a04 (cherry picked from commit 58741f2272f423a745e02fe044f9c4be1da8ffaf) --- .../lvm/wrapper/Aidl/BundleContext.cpp | 24 ++++++++++--------- .../lvm/wrapper/Aidl/BundleContext.h | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp index 97ba69f1ed..0db7a73b2c 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp @@ -36,7 +36,7 @@ RetCode BundleContext::init() { std::lock_guard lg(mMutex); // init with pre-defined preset NORMAL for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) { - mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i]; + mBandGainMdB[i] = lvm::kSoftPresets[0 /* normal */][i] * 100; } // allocate lvm instance @@ -214,7 +214,7 @@ RetCode BundleContext::limitLevel() { if (eqEnabled) { for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) { - float bandFactor = mBandGaindB[i] / 15.0; + float bandFactor = mBandGainMdB[i] / 1500.0; float bandCoefficient = lvm::kBandEnergyCoefficient[i]; float bandEnergy = bandFactor * bandCoefficient * bandCoefficient; if (bandEnergy > 0) energyContribution += bandEnergy; @@ -223,8 +223,8 @@ RetCode BundleContext::limitLevel() { // cross EQ coefficients float bandFactorSum = 0; for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) { - float bandFactor1 = mBandGaindB[i] / 15.0; - float bandFactor2 = mBandGaindB[i + 1] / 15.0; + float bandFactor1 = mBandGainMdB[i] / 1500.0; + float bandFactor2 = mBandGainMdB[i + 1] / 1500.0; if (bandFactor1 > 0 && bandFactor2 > 0) { float crossEnergy = @@ -246,7 +246,7 @@ RetCode BundleContext::limitLevel() { if (eqEnabled) { for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) { - float bandFactor = mBandGaindB[i] / 15.0; + float bandFactor = mBandGainMdB[i] / 1500.0; float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i]; float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient; if (bandEnergy > 0) energyBassBoost += bandEnergy; @@ -471,7 +471,7 @@ std::vector BundleContext::getEqualizerBandLevels() const bandLevels.reserve(lvm::MAX_NUM_BANDS); for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) { bandLevels.emplace_back( - Equalizer::BandLevel{static_cast(i), mBandGaindB[i] * 100}); + Equalizer::BandLevel{static_cast(i), mBandGainMdB[i]}); } return bandLevels; } @@ -505,9 +505,9 @@ RetCode BundleContext::updateControlParameter(const std::vector tempLevel(mBandGaindB); + std::array tempLevel(mBandGainMdB); for (const auto& it : bandLevels) { - tempLevel[it.index] = it.levelMb > 0 ? (it.levelMb + 50) / 100 : (it.levelMb - 50) / 100; + tempLevel[it.index] = it.levelMb; } LVM_ControlParams_t params; @@ -519,14 +519,16 @@ RetCode BundleContext::updateControlParameter(const std::vector 0 ? (tempLevel[i] + 50) / 100 : (tempLevel[i] - 50) / 100; } RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, ¶ms), RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed"); } - mBandGaindB = tempLevel; - LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB); + mBandGainMdB = tempLevel; + LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainMdB) + << "mdB"; return RetCode::SUCCESS; } diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h index 072296e552..62bb6e4f4e 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h @@ -135,7 +135,7 @@ class BundleContext final : public EffectContext { int mBassStrengthSaved = 0; // Equalizer int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */ - std::array mBandGaindB; + std::array mBandGainMdB; /* band gain in millibels */ // Virtualizer int mVirtStrengthSaved = 0; /* Conversion between Get/Set */ bool mVirtualizerTempDisabled = false; From cc4a76d22080fc8954132c9cd47c1264bab5a925 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 22 Jun 2023 21:56:08 +0000 Subject: [PATCH 030/148] Revert "Implement VolToDb with audio_utils_power_from_amplitude" This reverts commit 9a0d5e016155c8be8b0d474d26602bf89914fc14. Reason for revert: DroidMonitor: Potential culprit for b/288445440 - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted. Change-Id: Idf2a9826e0c9014e46bf3585ffccdac897ebdb89 --- .../lvm/wrapper/Aidl/BundleContext.cpp | 35 ++++++++++--------- .../lvm/wrapper/Aidl/BundleContext.h | 10 +++--- .../lvm/wrapper/Aidl/EffectBundleAidl.cpp | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp index b42c2f9397..d026e2b672 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp @@ -18,7 +18,6 @@ #define LOG_TAG "BundleContext" #include -#include #include #include "BundleContext.h" @@ -398,10 +397,15 @@ LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const { return db_fix; } -/* static */ -float BundleContext::VolToDb(float vol) { - float dB = audio_utils_power_from_amplitude(vol); - return std::max(dB, -96.f); +// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude +int16_t BundleContext::VolToDb(uint32_t vol) const { + int16_t dB; + + dB = LVC_ToDB_s32Tos16(vol << 7); + dB = (dB + 8) >> 4; + dB = (dB < -96) ? -96 : dB; + + return dB; } RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { @@ -409,12 +413,11 @@ RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { LVM_ReturnStatus_en status = LVM_SUCCESS; // Convert volume to dB - float leftdB = VolToDb(volume.left); - float rightdB = VolToDb(volume.right); - - float maxdB = std::max(leftdB, rightdB); - float pandB = rightdB - leftdB; - setVolumeLevel(maxdB); + int leftdB = VolToDb(volume.left); + int rightdB = VolToDb(volume.right); + int maxdB = std::max(leftdB, rightdB); + int pandB = rightdB - leftdB; + setVolumeLevel(maxdB * 100); LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB; { @@ -548,18 +551,18 @@ RetCode BundleContext::setBassBoostStrength(int strength) { return limitLevel(); } -RetCode BundleContext::setVolumeLevel(float level) { +RetCode BundleContext::setVolumeLevel(int level) { if (mMuteEnabled) { - mLevelSaved = level; + mLevelSaved = level / 100; } else { - mVolume = level; + mVolume = level / 100; } LOG(INFO) << __func__ << " success with level " << level; return limitLevel(); } -float BundleContext::getVolumeLevel() const { - return (mMuteEnabled ? mLevelSaved : mVolume); +int BundleContext::getVolumeLevel() const { + return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100); } RetCode BundleContext::setVolumeMute(bool mute) { diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h index 072296e552..47d5e5a66c 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h @@ -80,8 +80,8 @@ class BundleContext final : public EffectContext { RetCode setBassBoostStrength(int strength); int getBassBoostStrength() const { return mBassStrengthSaved; } - RetCode setVolumeLevel(float level); - float getVolumeLevel() const; + RetCode setVolumeLevel(int level); + int getVolumeLevel() const; RetCode setVolumeMute(bool mute); int getVolumeMute() const { return mMuteEnabled; } @@ -141,14 +141,14 @@ class BundleContext final : public EffectContext { bool mVirtualizerTempDisabled = false; ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice; // Volume - float mLevelSaved = 0; /* for when mute is set, level must be saved */ - float mVolume = 0; + int mLevelSaved = 0; /* for when mute is set, level must be saved */ + int mVolume = 0; bool mMuteEnabled = false; /* Must store as mute = -96dB level */ void initControlParameter(LVM_ControlParams_t& params) const; void initHeadroomParameter(LVM_HeadroomParams_t& params) const; RetCode limitLevel(); - static float VolToDb(float vol); + int16_t VolToDb(uint32_t vol) const; LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const; RetCode updateControlParameter(const std::vector& bandLevels); bool isBandLevelIndexInRange(const std::vector& bandLevels) const; diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp index c2d5cbf68b..cd9fb604d7 100644 --- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp @@ -355,7 +355,7 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id, auto tag = id.get(); switch (tag) { case Volume::levelDb: { - volParam.set(static_cast(mContext->getVolumeLevel())); + volParam.set(mContext->getVolumeLevel()); break; } case Volume::mute: { From 23a2101548af072bc68094f0ba3b7748bfa6137f Mon Sep 17 00:00:00 2001 From: Liana Kazanova Date: Thu, 22 Jun 2023 21:56:09 +0000 Subject: [PATCH 031/148] Revert "Implement VolToDb with audio_utils_power_from_amplitude" This reverts commit 9a0d5e016155c8be8b0d474d26602bf89914fc14. Reason for revert:Potential culprit for b/288445440 - verifying through ABTD before revert submission. This is part of the standard investigation process, and does not mean your CL will be reverted. Change-Id: Id52a8a3918f17151e49af640dc030ea703b7d10c --- .../lvm/wrapper/Aidl/BundleContext.cpp | 35 ++++++++++--------- .../lvm/wrapper/Aidl/BundleContext.h | 10 +++--- .../lvm/wrapper/Aidl/EffectBundleAidl.cpp | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp index b42c2f9397..d026e2b672 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp @@ -18,7 +18,6 @@ #define LOG_TAG "BundleContext" #include -#include #include #include "BundleContext.h" @@ -398,10 +397,15 @@ LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const { return db_fix; } -/* static */ -float BundleContext::VolToDb(float vol) { - float dB = audio_utils_power_from_amplitude(vol); - return std::max(dB, -96.f); +// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude +int16_t BundleContext::VolToDb(uint32_t vol) const { + int16_t dB; + + dB = LVC_ToDB_s32Tos16(vol << 7); + dB = (dB + 8) >> 4; + dB = (dB < -96) ? -96 : dB; + + return dB; } RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { @@ -409,12 +413,11 @@ RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { LVM_ReturnStatus_en status = LVM_SUCCESS; // Convert volume to dB - float leftdB = VolToDb(volume.left); - float rightdB = VolToDb(volume.right); - - float maxdB = std::max(leftdB, rightdB); - float pandB = rightdB - leftdB; - setVolumeLevel(maxdB); + int leftdB = VolToDb(volume.left); + int rightdB = VolToDb(volume.right); + int maxdB = std::max(leftdB, rightdB); + int pandB = rightdB - leftdB; + setVolumeLevel(maxdB * 100); LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB; { @@ -548,18 +551,18 @@ RetCode BundleContext::setBassBoostStrength(int strength) { return limitLevel(); } -RetCode BundleContext::setVolumeLevel(float level) { +RetCode BundleContext::setVolumeLevel(int level) { if (mMuteEnabled) { - mLevelSaved = level; + mLevelSaved = level / 100; } else { - mVolume = level; + mVolume = level / 100; } LOG(INFO) << __func__ << " success with level " << level; return limitLevel(); } -float BundleContext::getVolumeLevel() const { - return (mMuteEnabled ? mLevelSaved : mVolume); +int BundleContext::getVolumeLevel() const { + return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100); } RetCode BundleContext::setVolumeMute(bool mute) { diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h index 072296e552..47d5e5a66c 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h @@ -80,8 +80,8 @@ class BundleContext final : public EffectContext { RetCode setBassBoostStrength(int strength); int getBassBoostStrength() const { return mBassStrengthSaved; } - RetCode setVolumeLevel(float level); - float getVolumeLevel() const; + RetCode setVolumeLevel(int level); + int getVolumeLevel() const; RetCode setVolumeMute(bool mute); int getVolumeMute() const { return mMuteEnabled; } @@ -141,14 +141,14 @@ class BundleContext final : public EffectContext { bool mVirtualizerTempDisabled = false; ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice; // Volume - float mLevelSaved = 0; /* for when mute is set, level must be saved */ - float mVolume = 0; + int mLevelSaved = 0; /* for when mute is set, level must be saved */ + int mVolume = 0; bool mMuteEnabled = false; /* Must store as mute = -96dB level */ void initControlParameter(LVM_ControlParams_t& params) const; void initHeadroomParameter(LVM_HeadroomParams_t& params) const; RetCode limitLevel(); - static float VolToDb(float vol); + int16_t VolToDb(uint32_t vol) const; LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const; RetCode updateControlParameter(const std::vector& bandLevels); bool isBandLevelIndexInRange(const std::vector& bandLevels) const; diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp index c2d5cbf68b..cd9fb604d7 100644 --- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp @@ -355,7 +355,7 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id, auto tag = id.get(); switch (tag) { case Volume::levelDb: { - volParam.set(static_cast(mContext->getVolumeLevel())); + volParam.set(mContext->getVolumeLevel()); break; } case Volume::mute: { From 484043a9973fc4e163939f302780c3c85fca5275 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 22 Jun 2023 22:49:59 +0000 Subject: [PATCH 032/148] Revert "Revert "Implement VolToDb with audio_utils_power_from_amplitude"" This reverts commit cc4a76d22080fc8954132c9cd47c1264bab5a925. Reason for revert: ag/23784775 fixed b/288445440, no need to revert this one Change-Id: Iec90afd07ac83d3dd733e9c0d692128a19c3562f --- .../lvm/wrapper/Aidl/BundleContext.cpp | 35 +++++++++---------- .../lvm/wrapper/Aidl/BundleContext.h | 10 +++--- .../lvm/wrapper/Aidl/EffectBundleAidl.cpp | 2 +- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp index d026e2b672..b42c2f9397 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "BundleContext" #include +#include #include #include "BundleContext.h" @@ -397,15 +398,10 @@ LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const { return db_fix; } -// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude -int16_t BundleContext::VolToDb(uint32_t vol) const { - int16_t dB; - - dB = LVC_ToDB_s32Tos16(vol << 7); - dB = (dB + 8) >> 4; - dB = (dB < -96) ? -96 : dB; - - return dB; +/* static */ +float BundleContext::VolToDb(float vol) { + float dB = audio_utils_power_from_amplitude(vol); + return std::max(dB, -96.f); } RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { @@ -413,11 +409,12 @@ RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) { LVM_ReturnStatus_en status = LVM_SUCCESS; // Convert volume to dB - int leftdB = VolToDb(volume.left); - int rightdB = VolToDb(volume.right); - int maxdB = std::max(leftdB, rightdB); - int pandB = rightdB - leftdB; - setVolumeLevel(maxdB * 100); + float leftdB = VolToDb(volume.left); + float rightdB = VolToDb(volume.right); + + float maxdB = std::max(leftdB, rightdB); + float pandB = rightdB - leftdB; + setVolumeLevel(maxdB); LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB; { @@ -551,18 +548,18 @@ RetCode BundleContext::setBassBoostStrength(int strength) { return limitLevel(); } -RetCode BundleContext::setVolumeLevel(int level) { +RetCode BundleContext::setVolumeLevel(float level) { if (mMuteEnabled) { - mLevelSaved = level / 100; + mLevelSaved = level; } else { - mVolume = level / 100; + mVolume = level; } LOG(INFO) << __func__ << " success with level " << level; return limitLevel(); } -int BundleContext::getVolumeLevel() const { - return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100); +float BundleContext::getVolumeLevel() const { + return (mMuteEnabled ? mLevelSaved : mVolume); } RetCode BundleContext::setVolumeMute(bool mute) { diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h index 47d5e5a66c..072296e552 100644 --- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h +++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h @@ -80,8 +80,8 @@ class BundleContext final : public EffectContext { RetCode setBassBoostStrength(int strength); int getBassBoostStrength() const { return mBassStrengthSaved; } - RetCode setVolumeLevel(int level); - int getVolumeLevel() const; + RetCode setVolumeLevel(float level); + float getVolumeLevel() const; RetCode setVolumeMute(bool mute); int getVolumeMute() const { return mMuteEnabled; } @@ -141,14 +141,14 @@ class BundleContext final : public EffectContext { bool mVirtualizerTempDisabled = false; ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice; // Volume - int mLevelSaved = 0; /* for when mute is set, level must be saved */ - int mVolume = 0; + float mLevelSaved = 0; /* for when mute is set, level must be saved */ + float mVolume = 0; bool mMuteEnabled = false; /* Must store as mute = -96dB level */ void initControlParameter(LVM_ControlParams_t& params) const; void initHeadroomParameter(LVM_HeadroomParams_t& params) const; RetCode limitLevel(); - int16_t VolToDb(uint32_t vol) const; + static float VolToDb(float vol); LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const; RetCode updateControlParameter(const std::vector& bandLevels); bool isBandLevelIndexInRange(const std::vector& bandLevels) const; diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp index cd9fb604d7..c2d5cbf68b 100644 --- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp @@ -355,7 +355,7 @@ ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id, auto tag = id.get(); switch (tag) { case Volume::levelDb: { - volParam.set(mContext->getVolumeLevel()); + volParam.set(static_cast(mContext->getVolumeLevel())); break; } case Volume::mute: { From 8b11bc9a386bb01bd168607695d41f5197fdbd61 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Mon, 26 Jun 2023 11:24:35 -0700 Subject: [PATCH 033/148] Revert "Listen for foreground AppOps changes" This reverts commit 7370c8442e6649ef398402395e7f8c8eb6121bb9. Top VOIP apps rely on the ability to record audio in the background without capabilities. Fix breaks top CUJs, needs to be re-evaluated. Reason for revert: b/285898282, b/268724205 Bug: 268724205 Test: Manual verification of Meet Change-Id: Ie2b57f5d2247b6f771e1f6095e993d749ad685f9 --- services/audiopolicy/service/AudioPolicyService.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 936794999b..df0c59f6fa 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -1917,7 +1917,6 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), - AppOpsManager::WATCH_FOREGROUND_CHANGES, mOpCallback); } From d55ed3b3216501f319b8a6cf70255ac249d6f2ff Mon Sep 17 00:00:00 2001 From: Wonsik Kim Date: Thu, 22 Jun 2023 14:42:17 -0700 Subject: [PATCH 034/148] CCodec: clear deadline after component start returns Bug: 287391419 Test: atest android.videocodec.cts.VideoEncoderMinMaxTest (cherry picked from https://android-review.googlesource.com/q/commit:d86c96badfadb21b09aec51464c2814143b8bafa) Merged-In: I0477afb011716edb16f5a4074f1a4f29ecf8d312 Change-Id: I0477afb011716edb16f5a4074f1a4f29ecf8d312 --- media/codec2/sfplugin/CCodec.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp index 5e53acc46a..86fd8ab29e 100644 --- a/media/codec2/sfplugin/CCodec.cpp +++ b/media/codec2/sfplugin/CCodec.cpp @@ -1808,6 +1808,10 @@ void CCodec::start() { ACTION_CODE_FATAL); return; } + + // clear the deadline after the component starts + setDeadline(TimePoint::max(), 0ms, "none"); + sp inputFormat; sp outputFormat; status_t err2 = OK; From 7434e81670e459054a94fd1bb51a963547440b0e Mon Sep 17 00:00:00 2001 From: jiabin Date: Tue, 27 Jun 2023 18:22:35 +0000 Subject: [PATCH 035/148] Accessing tee patches with holding the thread lock. There is race that the tee patches can be updated from thread loop and the tee patches can also be accessed when the client has some operations. In that case, it will be safe to access tee patches with holding the thread lock. Bug: 286576245 Test: atest AudioPlaybackCaptureTest Change-Id: Ia704350ed5b3c914448ee609da33b867e3aa7626 --- services/audioflinger/AudioFlinger.cpp | 2 +- services/audioflinger/PlaybackTracks.h | 7 ++++--- services/audioflinger/Threads.cpp | 2 +- services/audioflinger/Tracks.cpp | 26 ++++++++++++++------------ 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 325adfa568..817d3a4208 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -4000,7 +4000,7 @@ void AudioFlinger::updateSecondaryOutputsForTrack_l( patchTrack->setPeerProxy(patchRecord, true /* holdReference */); patchRecord->setPeerProxy(patchTrack, false /* holdReference */); } - track->setTeePatchesToUpdate(std::move(teePatches)); + track->setTeePatchesToUpdate_l(std::move(teePatches)); } sp AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type, diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 0e1a3c9eec..d485ccc387 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -187,8 +187,8 @@ class Track : public TrackBase, public VolumeProvider { sp getExternalVibration() const { return mExternalVibration; } // This function should be called with holding thread lock. - void updateTeePatches(); - void setTeePatchesToUpdate(TeePatches teePatchesToUpdate); + void updateTeePatches_l(); + void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate); void tallyUnderrunFrames(size_t frames) override { if (isOut()) { // we expect this from output tracks only @@ -335,8 +335,9 @@ class Track : public TrackBase, public VolumeProvider { private: void interceptBuffer(const AudioBufferProvider::Buffer& buffer); + // Must hold thread lock to access tee patches template - void forEachTeePatchTrack(F f) { + void forEachTeePatchTrack_l(F f) { for (auto& tp : mTeePatches) { f(tp.patchTrack); } }; diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 700bdd2f15..d86042fa3e 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -4100,7 +4100,7 @@ NO_THREAD_SAFETY_ANALYSIS // manual locking of AudioFlinger setHalLatencyMode_l(); for (const auto &track : mActiveTracks ) { - track->updateTeePatches(); + track->updateTeePatches_l(); } // signal actual start of output stream when the render position reported by the kernel diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 7d2c4db231..7f99599e80 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -779,12 +779,12 @@ void AudioFlinger::PlaybackThread::Track::destroy() Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); wasActive = playbackThread->destroyTrack_l(this); + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); }); } if (isExternalTrack() && !wasActive) { AudioSystem::releaseOutput(mPortId); } } - forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); }); } void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result) @@ -1157,12 +1157,13 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev buffer.mFrameCount = 1; (void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/); } + if (status == NO_ERROR) { + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); }); + } } else { status = BAD_VALUE; } if (status == NO_ERROR) { - forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); }); - // send format to AudioManager for playback activity monitoring sp audioManager = thread->mAudioFlinger->getOrCreateAudioManager(); if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) { @@ -1212,8 +1213,8 @@ void AudioFlinger::PlaybackThread::Track::stop() ALOGV("%s(%d): not stopping/stopped => stopping/stopped on thread %d", __func__, mId, (int)mThreadIoHandle); } + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->stop(); }); } - forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); }); } void AudioFlinger::PlaybackThread::Track::pause() @@ -1248,9 +1249,9 @@ void AudioFlinger::PlaybackThread::Track::pause() default: break; } + // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss. + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->pause(); }); } - // Pausing the TeePatch to avoid a glitch on underrun, at the cost of buffered audio loss. - forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); }); } void AudioFlinger::PlaybackThread::Track::flush() @@ -1311,9 +1312,10 @@ void AudioFlinger::PlaybackThread::Track::flush() // before mixer thread can run. This is important when offloading // because the hardware buffer could hold a large amount of audio playbackThread->broadcast_l(); + // Flush the Tee to avoid on resume playing old data and glitching on the transition to + // new data + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->flush(); }); } - // Flush the Tee to avoid on resume playing old data and glitching on the transition to new data - forEachTeePatchTrack([](auto patchTrack) { patchTrack->flush(); }); } // must be called with thread lock held @@ -1491,19 +1493,19 @@ void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backI *backInserter++ = metadata; } -void AudioFlinger::PlaybackThread::Track::updateTeePatches() { +void AudioFlinger::PlaybackThread::Track::updateTeePatches_l() { if (mTeePatchesToUpdate.has_value()) { - forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); }); + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); }); mTeePatches = mTeePatchesToUpdate.value(); if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING || mState == TrackBase::STOPPING_1) { - forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); }); + forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->start(); }); } mTeePatchesToUpdate.reset(); } } -void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) { +void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) { ALOGW_IF(mTeePatchesToUpdate.has_value(), "%s, existing tee patches to update will be ignored", __func__); mTeePatchesToUpdate = std::move(teePatchesToUpdate); From 166663a1d2879a5a0dfc74cec0d68e3221708723 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Tue, 27 Jun 2023 19:16:24 -0700 Subject: [PATCH 036/148] Prevent audioflinger battery notes leak Ensure battery notes from audioflinger are encapsulated in an RAII object so noteStart is always properly matched. Remove uid refcounting in audioserver, since it already exists in the battery notifier utility class, and is error-prone. As a byproduct, notes occur during track transitions rather than in the threadloop, which happens to avoid problematic blocking. Bump refcount mismatch logging to error. Bug: 259449389 Test: Manual verification of battery stats notes w/ multiple refs Change-Id: Ifc931a9ac46f37d662e42dd4696f0a62eec22c25 --- media/utils/BatteryNotifier.cpp | 4 +-- .../include/mediautils/BatteryNotifier.h | 32 +++++++++++++++++++ services/audioflinger/AudioFlinger.h | 1 + services/audioflinger/Threads.cpp | 28 ++-------------- services/audioflinger/Threads.h | 2 -- services/audioflinger/TrackBase.h | 19 +++++++++++ 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/media/utils/BatteryNotifier.cpp b/media/utils/BatteryNotifier.cpp index 09bc042265..7762c24478 100644 --- a/media/utils/BatteryNotifier.cpp +++ b/media/utils/BatteryNotifier.cpp @@ -85,8 +85,8 @@ void BatteryNotifier::noteStartAudio(uid_t uid) { void BatteryNotifier::noteStopAudio(uid_t uid) { Mutex::Autolock _l(mLock); - if (mAudioRefCounts.find(uid) == mAudioRefCounts.end()) { - ALOGW("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid); + if (mAudioRefCounts.find(uid) == mAudioRefCounts.end() || (mAudioRefCounts[uid] == 0)) { + ALOGE("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid); return; } diff --git a/media/utils/include/mediautils/BatteryNotifier.h b/media/utils/include/mediautils/BatteryNotifier.h index 3812d7a874..73bed4a50f 100644 --- a/media/utils/include/mediautils/BatteryNotifier.h +++ b/media/utils/include/mediautils/BatteryNotifier.h @@ -68,6 +68,38 @@ class BatteryNotifier : public Singleton { sp getBatteryService_l(); }; +namespace mediautils { +class BatteryStatsAudioHandle { + public: + static constexpr uid_t INVALID_UID = static_cast(-1); + + explicit BatteryStatsAudioHandle(uid_t uid) : mUid(uid) { + if (uid != INVALID_UID) { + BatteryNotifier::getInstance().noteStartAudio(mUid); + } + } + + BatteryStatsAudioHandle(BatteryStatsAudioHandle&& other) : mUid(other.mUid) { + other.mUid = INVALID_UID; + } + + BatteryStatsAudioHandle(const BatteryStatsAudioHandle& other) = delete; + + BatteryStatsAudioHandle& operator=(const BatteryStatsAudioHandle& other) = delete; + + BatteryStatsAudioHandle& operator=(BatteryStatsAudioHandle&& other) = delete; + + ~BatteryStatsAudioHandle() { + if (mUid != INVALID_UID) { + BatteryNotifier::getInstance().noteStopAudio(mUid); + } + } + + private: + // Logically const + uid_t mUid = INVALID_UID; +}; +} // namespace mediautils } // namespace android #endif // MEDIA_BATTERY_NOTIFIER_H diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index c3ca1b0efd..7058a25495 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 700bdd2f15..45a5c09e73 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -1877,7 +1877,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks::add(const sp &track) { logTrack("add", track); mActiveTracksGeneration++; mLatestActiveTrack = track; - ++mBatteryCounter[track->uid()].second; + track->beginBatteryAttribution(); mHasChanged = true; return mActiveTracks.add(track); } @@ -1891,7 +1891,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks::remove(const sp &track) { } logTrack("remove", track); mActiveTracksGeneration++; - --mBatteryCounter[track->uid()].second; + track->endBatteryAttribution(); // mLatestActiveTrack is not cleared even if is the same as track. mHasChanged = true; #ifdef TEE_SINK @@ -1904,14 +1904,13 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks::remove(const sp &track) { template void AudioFlinger::ThreadBase::ActiveTracks::clear() { for (const sp &track : mActiveTracks) { - BatteryNotifier::getInstance().noteStopAudio(track->uid()); + track->endBatteryAttribution(); logTrack("clear", track); } mLastActiveTracksGeneration = mActiveTracksGeneration; if (!mActiveTracks.empty()) { mHasChanged = true; } mActiveTracks.clear(); mLatestActiveTrack.clear(); - mBatteryCounter.clear(); } template @@ -1922,27 +1921,6 @@ void AudioFlinger::ThreadBase::ActiveTracks::updatePowerState( thread->updateWakeLockUids_l(getWakeLockUids()); mLastActiveTracksGeneration = mActiveTracksGeneration; } - - // Updates BatteryNotifier uids - for (auto it = mBatteryCounter.begin(); it != mBatteryCounter.end();) { - const uid_t uid = it->first; - ssize_t &previous = it->second.first; - ssize_t ¤t = it->second.second; - if (current > 0) { - if (previous == 0) { - BatteryNotifier::getInstance().noteStartAudio(uid); - } - previous = current; - ++it; - } else if (current == 0) { - if (previous > 0) { - BatteryNotifier::getInstance().noteStopAudio(uid); - } - it = mBatteryCounter.erase(it); // std::map<> is stable on iterator erase. - } else /* (current < 0) */ { - LOG_ALWAYS_FATAL("negative battery count %zd", current); - } - } } template diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index e88134b576..7d16a0b54a 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -826,8 +826,6 @@ class ThreadBase : public Thread { return wakeLockUids; // moved by underlying SharedBuffer } - std::map> - mBatteryCounter; SortedVector> mActiveTracks; int mActiveTracksGeneration; int mLastActiveTracksGeneration; diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 254fb91c0c..5adeb1f32e 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -270,6 +270,23 @@ class TrackBase : public ExtendedAudioBufferProvider, public RefBase { /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */ void setMetadataHasChanged() { mChangeNotified.clear(); } + /** + * Called when a track moves to active state to record its contribution to battery usage. + * Track state transitions should eventually be handled within the track class. + */ + void beginBatteryAttribution() { + mBatteryStatsHolder.emplace(uid()); + } + + /** + * Called when a track moves out of the active state to record its contribution + * to battery usage. + */ + void endBatteryAttribution() { + mBatteryStatsHolder.reset(); + } + + protected: DISALLOW_COPY_AND_ASSIGN(TrackBase); @@ -412,6 +429,8 @@ class TrackBase : public ExtendedAudioBufferProvider, public RefBase { // If the last track change was notified to the client with readAndClearHasChanged std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT; + // RAII object for battery stats book-keeping + std::optional mBatteryStatsHolder; }; // PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord. From 321b5c9d45a1d15bb289dcd139e43287185dbd36 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 29 Jun 2023 11:44:54 +0200 Subject: [PATCH 037/148] libaudiohal: implement supportsBluetoothVariableLatency for HIDL Implement supportsBluetoothVariableLatency for HIDL by way of getParameters API. Bug: 287695426 Test: verify that low latency mode is requested when TalkBack is playing Change-Id: Ibacbdf6cefbcb96b6ac3cfd82b6d26a0e36c8a08 --- media/libaudiohal/impl/DeviceHalAidl.cpp | 2 +- media/libaudiohal/impl/DeviceHalAidl.h | 2 +- media/libaudiohal/impl/DeviceHalHidl.cpp | 22 +++++++++++++++++++ media/libaudiohal/impl/DeviceHalHidl.h | 5 +---- .../media/audiohal/DeviceHalInterface.h | 2 +- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index ae151908c5..c7d7f69a15 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -996,7 +996,7 @@ status_t DeviceHalAidl::dump(int fd, const Vector& args) { return mModule->dump(fd, Args(args).args(), args.size()); } -int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) { +status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) { TIME_CHECK(); if (!mModule) return NO_INIT; if (supports == nullptr) { diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index 74a8b51bf5..6566de13f6 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -165,7 +165,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, error::Result getHwAvSync() override; - int32_t supportsBluetoothVariableLatency(bool* supports __unused) override; + status_t supportsBluetoothVariableLatency(bool* supports __unused) override; status_t getSoundDoseInterface(const std::string& module, ::ndk::SpAIBinder* soundDoseBinder) override; diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp index f96d419393..0d71fd338c 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.cpp +++ b/media/libaudiohal/impl/DeviceHalHidl.cpp @@ -684,4 +684,26 @@ status_t DeviceHalHidl::getSoundDoseInterface(const std::string& module, } #endif +status_t DeviceHalHidl::supportsBluetoothVariableLatency(bool* supports) { + if (supports == nullptr) { + return BAD_VALUE; + } + *supports = false; + + String8 reply; + status_t status = getParameters( + String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), &reply); + if (status != NO_ERROR) { + return status; + } + AudioParameter replyParams(reply); + String8 trueOrFalse; + status = replyParams.get( + String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), trueOrFalse); + if (status != NO_ERROR) { + return status; + } + *supports = trueOrFalse == AudioParameter::valueTrue; + return NO_ERROR; +} } // namespace android diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h index 989c1f520f..1a1db330ee 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.h +++ b/media/libaudiohal/impl/DeviceHalHidl.h @@ -127,10 +127,7 @@ class DeviceHalHidl : public DeviceHalInterface, public CoreConversionHelperHidl return INVALID_OPERATION; } - int32_t supportsBluetoothVariableLatency(bool* supports __unused) override { - // TODO: Implement the HAL query when moving to AIDL HAL. - return INVALID_OPERATION; - } + status_t supportsBluetoothVariableLatency(bool* supports) override; status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override; diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h index a965709908..dd14135fec 100644 --- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h +++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h @@ -142,7 +142,7 @@ class DeviceHalInterface : public virtual RefBase virtual int32_t getAAudioMixerBurstCount() = 0; virtual int32_t getAAudioHardwareBurstMinUsec() = 0; - virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0; + virtual status_t supportsBluetoothVariableLatency(bool* supports) = 0; // Update the connection status of an external device. virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0; From b01088f54f7a1ac4881738a07022937ffc3c4f6d Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 29 Jun 2023 01:39:54 +0000 Subject: [PATCH 038/148] Fix processing effect uuid null Bug: 289160252 Bug: 271500140 Test: Enable AIDL and check processing loading on Cuttlefish Change-Id: I28436bb45431fdc2be2d8b82546d8b06d66e5108 Merged-In: I28436bb45431fdc2be2d8b82546d8b06d66e5108 --- media/libaudiohal/impl/EffectsFactoryHalAidl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp index 1c5e4742c7..94b04f5175 100644 --- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp @@ -287,7 +287,7 @@ std::shared_ptr EffectsFactoryHalAidl::getProc if (const auto uuid = ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(desc.common.id.uuid); uuid.ok()) { - static_cast(effect).uuid = uuid.value(); + static_cast(effect).uuid = uuid.value(); return std::make_shared(effect); } else { return nullptr; From 8ed6d79d97e09d9ed23f23fbd67f33764a417720 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 29 Jun 2023 11:44:54 +0200 Subject: [PATCH 039/148] libaudiohal: implement supportsBluetoothVariableLatency for HIDL Implement supportsBluetoothVariableLatency for HIDL by way of getParameters API. Bug: 287695426 Test: verify that low latency mode is requested when TalkBack is playing Change-Id: Ibacbdf6cefbcb96b6ac3cfd82b6d26a0e36c8a08 (cherry picked from commit 321b5c9d45a1d15bb289dcd139e43287185dbd36) --- media/libaudiohal/impl/DeviceHalAidl.cpp | 2 +- media/libaudiohal/impl/DeviceHalAidl.h | 2 +- media/libaudiohal/impl/DeviceHalHidl.cpp | 22 +++++++++++++++++++ media/libaudiohal/impl/DeviceHalHidl.h | 5 +---- .../media/audiohal/DeviceHalInterface.h | 2 +- 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index 3125e31100..de123f4680 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -951,7 +951,7 @@ status_t DeviceHalAidl::dump(int fd, const Vector& args) { return mModule->dump(fd, Args(args).args(), args.size()); } -int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) { +status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) { TIME_CHECK(); if (!mModule) return NO_INIT; if (supports == nullptr) { diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index 37d800b35e..613eb6372b 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -162,7 +162,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, error::Result getHwAvSync() override; - int32_t supportsBluetoothVariableLatency(bool* supports __unused) override; + status_t supportsBluetoothVariableLatency(bool* supports __unused) override; status_t getSoundDoseInterface(const std::string& module, ::ndk::SpAIBinder* soundDoseBinder) override; diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp index 826461f9a5..d043568eb6 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.cpp +++ b/media/libaudiohal/impl/DeviceHalHidl.cpp @@ -681,4 +681,26 @@ status_t DeviceHalHidl::getSoundDoseInterface(const std::string& module, } #endif +status_t DeviceHalHidl::supportsBluetoothVariableLatency(bool* supports) { + if (supports == nullptr) { + return BAD_VALUE; + } + *supports = false; + + String8 reply; + status_t status = getParameters( + String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), &reply); + if (status != NO_ERROR) { + return status; + } + AudioParameter replyParams(reply); + String8 trueOrFalse; + status = replyParams.get( + String8(AUDIO_PARAMETER_BT_VARIABLE_LATENCY_SUPPORTED), trueOrFalse); + if (status != NO_ERROR) { + return status; + } + *supports = trueOrFalse == AudioParameter::valueTrue; + return NO_ERROR; +} } // namespace android diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h index c5addde848..43ec4d7249 100644 --- a/media/libaudiohal/impl/DeviceHalHidl.h +++ b/media/libaudiohal/impl/DeviceHalHidl.h @@ -125,10 +125,7 @@ class DeviceHalHidl : public DeviceHalInterface, public CoreConversionHelperHidl return INVALID_OPERATION; } - int32_t supportsBluetoothVariableLatency(bool* supports __unused) override { - // TODO: Implement the HAL query when moving to AIDL HAL. - return INVALID_OPERATION; - } + status_t supportsBluetoothVariableLatency(bool* supports) override; status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override; diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h index 71e5e7ad9c..aab7244968 100644 --- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h +++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h @@ -142,7 +142,7 @@ class DeviceHalInterface : public virtual RefBase virtual int32_t getAAudioMixerBurstCount() = 0; virtual int32_t getAAudioHardwareBurstMinUsec() = 0; - virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0; + virtual status_t supportsBluetoothVariableLatency(bool* supports) = 0; // Update the connection status of an external device. virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0; From 98c519c942f2d6ed7cde4cfe00a0a9f04d7f4ba6 Mon Sep 17 00:00:00 2001 From: jiabin Date: Wed, 5 Jul 2023 17:34:21 +0000 Subject: [PATCH 040/148] Fix rerouting problem when bit-perfect playback starts. When bit-perfect playback starts, APM should reroute all clients that currently is routed to the bit-perfect sink to the bit-perfect output. Bug: 290054011 Test: atest audiopolicy_tests Change-Id: I70279cebb8dea51c06e4e34ac355354c1816c40f --- services/audiopolicy/managerdefault/AudioPolicyManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 3f2b19664c..5d56e7d043 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -2155,7 +2155,7 @@ status_t AudioPolicyManager::startOutput(audio_port_handle_t portId) PortHandleVector clientsToInvalidate; for (size_t i = 0; i < mOutputs.size(); i++) { if (mOutputs[i] == outputDesc || - !mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty()) { + mOutputs[i]->devices().filter(outputDesc->devices()).isEmpty()) { continue; } for (const auto& c : mOutputs[i]->getClientIterable()) { From 9367b90b521800cd1aa9f85720a8403edc22f8ce Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 29 Jun 2023 18:07:09 +0000 Subject: [PATCH 041/148] Support passing entire effect_param_t as vendor extension Copy entire effect_param_t into AIDL ParcelableHolder with DefaultExtension Bug: 271500140 Test: Enable AIDL Test: atest libAudioHalEffectParamTest Change-Id: I21829324e820dc68859000d912376a5e1b7d056b Merged-In: I21829324e820dc68859000d912376a5e1b7d056b --- .../AidlConversionEffect.cpp | 73 ++++++++----------- .../include/media/AidlConversionEffect.h | 37 +++++----- .../AidlConversionAec.cpp | 2 +- .../AidlConversionAgc1.cpp | 2 +- .../AidlConversionAgc2.cpp | 2 +- .../AidlConversionBassBoost.cpp | 2 +- .../AidlConversionDownmix.cpp | 2 +- .../AidlConversionDynamicsProcessing.cpp | 2 +- .../AidlConversionEnvReverb.cpp | 2 +- .../AidlConversionEq.cpp | 2 +- .../AidlConversionHapticGenerator.cpp | 2 +- .../AidlConversionLoudnessEnhancer.cpp | 2 +- .../AidlConversionNoiseSuppression.cpp | 2 +- .../AidlConversionPresetReverb.cpp | 2 +- .../AidlConversionSpatializer.cpp | 5 +- .../AidlConversionVendorExtension.cpp | 7 +- .../AidlConversionVirtualizer.cpp | 2 +- .../AidlConversionVisualizer.cpp | 2 +- .../tests/EffectsFactoryHalInterface_test.cpp | 61 ++++++++++------ 19 files changed, 106 insertions(+), 105 deletions(-) diff --git a/media/audioaidlconversion/AidlConversionEffect.cpp b/media/audioaidlconversion/AidlConversionEffect.cpp index 611cfab388..6f55f1bc46 100644 --- a/media/audioaidlconversion/AidlConversionEffect.cpp +++ b/media/audioaidlconversion/AidlConversionEffect.cpp @@ -52,6 +52,7 @@ using ::android::OK; using ::android::status_t; using ::android::base::unexpected; using ::android::effect::utils::EffectParamReader; +using ::android::effect::utils::EffectParamWrapper; using ::android::effect::utils::EffectParamWriter; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -408,40 +409,7 @@ legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy) { } } -/** - * Copy the parameter area of effect_param_t to DefaultExtension::bytes. - */ -ConversionResult legacy2aidl_EffectParameterReader_Param_VendorExtension( - EffectParamReader& param) { - size_t len = param.getParameterSize(); - DefaultExtension defaultExt; - defaultExt.bytes.resize(len); - RETURN_IF_ERROR(param.readFromParameter(defaultExt.bytes.data(), len)); - - VendorExtension ext; - ext.extension.setParcelable(defaultExt); - return ext; -} - -/** - * Copy the data area of effect_param_t to DefaultExtension::bytes. - */ -ConversionResult legacy2aidl_EffectParameterReader_Data_VendorExtension( - EffectParamReader& param) { - size_t len = param.getValueSize(); - DefaultExtension defaultExt; - defaultExt.bytes.resize(len); - RETURN_IF_ERROR(param.readFromValue(defaultExt.bytes.data(), len)); - - VendorExtension ext; - ext.extension.setParcelable(defaultExt); - return ext; -} - -/** - * Copy DefaultExtension::bytes to the data area of effect_param_t. - */ -ConversionResult aidl2legacy_VendorExtension_EffectParameterWriter_Data( +ConversionResult aidl2legacy_VendorExtension_EffectParameterWriter( EffectParamWriter& param, VendorExtension ext) { std::optional defaultExt; RETURN_IF_ERROR(ext.extension.getParcelable(&defaultExt)); @@ -449,26 +417,47 @@ ConversionResult aidl2legacy_VendorExtension_EffectParameterWriter_Dat return unexpected(BAD_VALUE); } - RETURN_IF_ERROR(param.writeToValue(defaultExt->bytes.data(), defaultExt->bytes.size())); + // DefaultExtension defaultValue = defaultExt->get(); + if (defaultExt->bytes.size() < sizeof(effect_param_t)) { + return unexpected(BAD_VALUE); + } + // verify data length with EffectParamWrapper, DefaultExtension array size should not smaller + // than (sizeof(effect_param_t) + paddedPSize + vSize) + EffectParamWrapper wrapper(*(effect_param_t*)defaultExt->bytes.data()); + if (sizeof(effect_param_t) + wrapper.getPaddedParameterSize() + wrapper.getValueSize() > + defaultExt->bytes.size()) { + return unexpected(BAD_VALUE); + } + RETURN_IF_ERROR(param.overwrite(wrapper.getEffectParam())); return OK; } -ConversionResult legacy2aidl_EffectParameterReader_ParameterExtension( +ConversionResult legacy2aidl_EffectParameterReader_VendorExtension( EffectParamReader& param) { - VendorExtension ext = - VALUE_OR_RETURN(legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); - return UNION_MAKE(Parameter, specific, UNION_MAKE(Parameter::Specific, vendorEffect, ext)); + size_t len = param.getTotalSize(); + DefaultExtension defaultExt; + defaultExt.bytes.resize(len); + + std::memcpy(defaultExt.bytes.data(), (void *)¶m.getEffectParam(), len); + + VendorExtension ext; + ext.extension.setParcelable(defaultExt); + return ext; } -ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter( +ConversionResult<::android::status_t> aidl2legacy_Parameter_EffectParameterWriter( const ::aidl::android::hardware::audio::effect::Parameter& aidl, EffectParamWriter& legacy) { VendorExtension ext = VALUE_OR_RETURN( (::aidl::android::getParameterSpecific(aidl))); - return VALUE_OR_RETURN_STATUS( - aidl2legacy_VendorExtension_EffectParameterWriter_Data(legacy, ext)); + return VALUE_OR_RETURN_STATUS(aidl2legacy_VendorExtension_EffectParameterWriter(legacy, ext)); +} + +ConversionResult legacy2aidl_EffectParameterReader_Parameter(EffectParamReader& param) { + VendorExtension ext = VALUE_OR_RETURN(legacy2aidl_EffectParameterReader_VendorExtension(param)); + return UNION_MAKE(Parameter, specific, UNION_MAKE(Parameter::Specific, vendorEffect, ext)); } } // namespace android diff --git a/media/audioaidlconversion/include/media/AidlConversionEffect.h b/media/audioaidlconversion/include/media/AidlConversionEffect.h index 5e245a741e..b03d06b69f 100644 --- a/media/audioaidlconversion/include/media/AidlConversionEffect.h +++ b/media/audioaidlconversion/include/media/AidlConversionEffect.h @@ -67,7 +67,7 @@ ConversionResult getParameterSpecificField(const P& u) { #define VENDOR_EXTENSION_GET_AND_RETURN(_effect, _tag, _param) \ { \ aidl::android::hardware::audio::effect::VendorExtension _extId = VALUE_OR_RETURN_STATUS( \ - aidl::android::legacy2aidl_EffectParameterReader_Param_VendorExtension(_param)); \ + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(_param)); \ aidl::android::hardware::audio::effect::Parameter::Id _id = \ MAKE_EXTENSION_PARAMETER_ID(_effect, _tag##Tag, _extId); \ aidl::android::hardware::audio::effect::Parameter _aidlParam; \ @@ -76,8 +76,7 @@ ConversionResult getParameterSpecificField(const P& u) { VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD( \ _aidlParam, _effect, _tag, _effect::vendor, VendorExtension)); \ return VALUE_OR_RETURN_STATUS( \ - aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(_aidlParam, \ - _param)); \ + aidl::android::aidl2legacy_Parameter_EffectParameterWriter(_aidlParam, _param)); \ } ConversionResult aidl2legacy_Flags_Type_uint32( @@ -157,26 +156,26 @@ ConversionResult aidl2legacy_Parameter_Visualizer_MeasurementMode_uint ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode> legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy); -ConversionResult<::aidl::android::hardware::audio::effect::Parameter> -legacy2aidl_EffectParameterReader_ParameterExtension( - ::android::effect::utils::EffectParamReader& param); -ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter( - const ::aidl::android::hardware::audio::effect::Parameter& aidl, - ::android::effect::utils::EffectParamWriter& legacy); - -ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension> -legacy2aidl_EffectParameterReader_Param_VendorExtension( - ::android::effect::utils::EffectParamReader& param); -ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension> -legacy2aidl_EffectParameterReader_Data_VendorExtension( - ::android::effect::utils::EffectParamReader& param); - +/** + * Read DefaultExtension from VendorExtension, and overwrite to the entire effect_param_t (both + * parameter and data area) with EffectParamWriter::overwrite. + */ ConversionResult<::android::status_t> aidl2legacy_VendorExtension_EffectParameterWriter_Data( ::android::effect::utils::EffectParamWriter& param, ::aidl::android::hardware::audio::effect::VendorExtension ext); -ConversionResult<::aidl::android::hardware::audio::effect::Parameter> -legacy2aidl_EffectParameterReader_ParameterExtension( +/** + * Copy the entire effect_param_t (both parameter and data area) to DefaultExtension::bytes, and + * write into VendorExtension. + */ +ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension> +legacy2aidl_EffectParameterReader_VendorExtension( ::android::effect::utils::EffectParamReader& param); +ConversionResult<::android::status_t> aidl2legacy_Parameter_EffectParameterWriter( + const ::aidl::android::hardware::audio::effect::Parameter& aidl, + ::android::effect::utils::EffectParamWriter& legacy); +ConversionResult<::aidl::android::hardware::audio::effect::Parameter> +legacy2aidl_EffectParameterReader_Parameter( + ::android::effect::utils::EffectParamReader& param); } // namespace android } // namespace aidl diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp index 92b77d8529..f5640b8ee0 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp @@ -67,7 +67,7 @@ status_t AidlConversionAec::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, vendor, ext); RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp index 1363ba4e37..03606f4f09 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp @@ -90,7 +90,7 @@ status_t AidlConversionAgc1::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1, vendor, ext); return statusTFromBinderStatus(mEffect->setParameter(aidlParam)); diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp index b35a1c68b6..b9a5b02bbc 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp @@ -68,7 +68,7 @@ status_t AidlConversionAgc2::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2, vendor, ext); break; diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp index 7c6a5a2519..8df56b0798 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp @@ -66,7 +66,7 @@ status_t AidlConversionBassBoost::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, vendor, ext); break; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp index b57971ccfc..2b98e212de 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp @@ -60,7 +60,7 @@ status_t AidlConversionDownmix::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(Downmix, downmix, vendor, ext); } } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp index fe845ab9e1..89f8b83d09 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp @@ -119,7 +119,7 @@ status_t AidlConversionDp::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, vendor, ext); break; diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp index 754da43d6a..fcade684aa 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp @@ -168,7 +168,7 @@ status_t AidlConversionEnvReverb::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(EnvironmentalReverb, environmentalReverb, vendor, ext); RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp index fc867c7270..ca6ff880bb 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp @@ -103,7 +103,7 @@ status_t AidlConversionEq::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, vendor, ext); break; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp index 73430ba2c3..bdee7b65fb 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp @@ -79,7 +79,7 @@ status_t AidlConversionHapticGenerator::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vendor, ext); break; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp index 31eec65c06..a0526e6ea4 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp @@ -58,7 +58,7 @@ status_t AidlConversionLoudnessEnhancer::setParameter(EffectParamReader& param) default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, vendor, ext); break; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp index 7c34ed7e2c..bf75e4a3cc 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp @@ -63,7 +63,7 @@ status_t AidlConversionNoiseSuppression::setParameter(EffectParamReader& param) default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, vendor, ext); break; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp index e936aef9dc..3cac5910c5 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp @@ -61,7 +61,7 @@ status_t AidlConversionPresetReverb::setParameter(EffectParamReader& param) { } else { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(PresetReverb, presetReverb, vendor, ext); } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp index eadd6c3560..ff0c32bc7c 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp @@ -44,7 +44,7 @@ using utils::EffectParamWriter; status_t AidlConversionSpatializer::setParameter(EffectParamReader& param) { Parameter aidlParam = VALUE_OR_RETURN_STATUS( - ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param)); + ::aidl::android::legacy2aidl_EffectParameterReader_Parameter(param)); return statusTFromBinderStatus(mEffect->setParameter(aidlParam)); } @@ -64,8 +64,7 @@ status_t AidlConversionSpatializer::getParameter(EffectParamWriter& param) { RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam))); // copy the AIDL extension data back to effect_param_t return VALUE_OR_RETURN_STATUS( - ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam, - param)); + ::aidl::android::aidl2legacy_Parameter_EffectParameterWriter(aidlParam, param)); } } // namespace effect diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp index 488d5cd9b8..2c29c7d806 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp @@ -52,20 +52,19 @@ using utils::EffectParamWriter; */ status_t AidlConversionVendorExtension::setParameter(EffectParamReader& param) { Parameter aidlParam = VALUE_OR_RETURN_STATUS( - ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param)); + ::aidl::android::legacy2aidl_EffectParameterReader_Parameter(param)); return statusTFromBinderStatus(mEffect->setParameter(aidlParam)); } status_t AidlConversionVendorExtension::getParameter(EffectParamWriter& param) { VendorExtension extId = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Param_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, extId); Parameter aidlParam; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam))); // copy the AIDL extension data back to effect_param_t return VALUE_OR_RETURN_STATUS( - ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam, - param)); + ::aidl::android::aidl2legacy_Parameter_EffectParameterWriter(aidlParam, param)); } } // namespace effect diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp index c95c3a970a..cad0068098 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp @@ -77,7 +77,7 @@ status_t AidlConversionVirtualizer::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, vendor, ext); break; } diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp index b4440ee541..18d0d950d2 100644 --- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp +++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp @@ -75,7 +75,7 @@ status_t AidlConversionVisualizer::setParameter(EffectParamReader& param) { default: { // for vendor extension, copy data area to the DefaultExtension, parameter ignored VendorExtension ext = VALUE_OR_RETURN_STATUS( - aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param)); + aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param)); aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, vendor, ext); break; } diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp index 63f895f49c..2854496255 100644 --- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp +++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp @@ -16,6 +16,7 @@ //#define LOG_NDEBUG 0 #include +#include #include #include #include @@ -24,8 +25,11 @@ #define LOG_TAG "EffectsFactoryHalInterfaceTest" #include +#include #include #include +#include +#include #include #include #include @@ -36,17 +40,15 @@ #include #include #include -#include - -#include #include #include namespace android { +using ::aidl::android::media::audio::common::AudioUuid; +using ::android::audio::utils::toString; using effect::utils::EffectParamReader; using effect::utils::EffectParamWriter; -using ::aidl::android::media::audio::common::AudioUuid; // EffectsFactoryHalInterface TEST(libAudioHalTest, createEffectsFactoryHalInterface) { @@ -195,7 +197,8 @@ using EffectParamTestTuple = static const effect_uuid_t EXTEND_EFFECT_TYPE_UUID = { 0xfa81dbde, 0x588b, 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; - +constexpr std::array kVendorExtensionData({0xff, 0x5, 0x50, 0xab, 0xcd, 0x00, 0xbd, + 0xdb, 0xee, 0xff}); std::vector testPairs = { std::make_tuple(FX_IID_AEC, createEffectParamCombination(AEC_PARAM_ECHO_DELAY, 0xff /* echoDelayMs */, @@ -203,12 +206,9 @@ std::vector testPairs = { std::make_tuple(FX_IID_AGC, createEffectParamCombination(AGC_PARAM_TARGET_LEVEL, 20 /* targetLevel */, sizeof(int16_t) /* returnValueSize */)), - std::make_tuple(FX_IID_AGC2, createEffectParamCombination( - AGC2_PARAM_FIXED_DIGITAL_GAIN, 15 /* digitalGainDb */, - sizeof(int32_t) /* returnValueSize */)), std::make_tuple(SL_IID_BASSBOOST, createEffectParamCombination(BASSBOOST_PARAM_STRENGTH, 20 /* strength */, - sizeof(int32_t) /* returnValueSize */)), + sizeof(int16_t) /* returnValueSize */)), std::make_tuple(EFFECT_UIID_DOWNMIX, createEffectParamCombination(DOWNMIX_PARAM_TYPE, DOWNMIX_TYPE_FOLD, sizeof(int16_t) /* returnValueSize */)), @@ -216,13 +216,6 @@ std::vector testPairs = { createEffectParamCombination( std::array({DP_PARAM_INPUT_GAIN, 0 /* channel */}), 30 /* gainDb */, sizeof(int32_t) /* returnValueSize */)), - std::make_tuple( - FX_IID_HAPTICGENERATOR, - createEffectParamCombination( - HG_PARAM_HAPTIC_INTENSITY, - std::array( - {1, uint32_t(::android::os::HapticScale::HIGH) /* scale */}), - 0 /* returnValueSize */)), std::make_tuple( FX_IID_LOUDNESS_ENHANCER, createEffectParamCombination(LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB, 5 /* gain */, @@ -231,7 +224,8 @@ std::vector testPairs = { createEffectParamCombination(NS_PARAM_LEVEL, 1 /* level */, sizeof(int32_t) /* returnValueSize */)), std::make_tuple(&EXTEND_EFFECT_TYPE_UUID, - createEffectParamCombination(1, 0xbead, sizeof(int32_t)))}; + createEffectParamCombination(8, kVendorExtensionData, + sizeof(kVendorExtensionData)))}; class libAudioHalEffectParamTest : public ::testing::TestWithParam { public: @@ -255,7 +249,9 @@ class libAudioHalEffectParamTest : public ::testing::TestWithParam interface = createEffectHal(desc); ASSERT_NE(nullptr, interface); @@ -264,9 +260,11 @@ class libAudioHalEffectParamTest : public ::testing::TestWithParam& interface) { - uint32_t initReply = 0; - uint32_t initReplySize = sizeof(initReply); - ASSERT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &initReplySize, &initReply)); + uint32_t reply = 0; + uint32_t replySize = sizeof(reply); + ASSERT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &replySize, &reply)); + ASSERT_EQ(OK, interface->command(EFFECT_CMD_SET_CONFIG, sizeof(mEffectConfig), + &mEffectConfig, &replySize, &reply)); } void TearDown() override { @@ -311,7 +309,7 @@ class libAudioHalEffectParamTest : public ::testing::TestWithParam response(mCombination->valueSize); EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize)) << " try get valueSize " << mCombination->valueSize << " from " - << parameterGet.toString(); + << parameterGet.toString() << " set " << parameterSet->toString(); EXPECT_EQ(response, mExpectedValue); } } @@ -323,6 +321,23 @@ class libAudioHalEffectParamTest : public ::testing::TestWithParam mExpectedValue; const std::vector mDescs; std::vector> mHalInterfaces; + effect_config_t mEffectConfig = {.inputCfg = {.accessMode = EFFECT_BUFFER_ACCESS_READ, + .format = AUDIO_FORMAT_PCM_FLOAT, + .bufferProvider.getBuffer = nullptr, + .bufferProvider.releaseBuffer = nullptr, + .bufferProvider.cookie = nullptr, + .mask = EFFECT_CONFIG_ALL, + .samplingRate = 48000, + .channels = AUDIO_CHANNEL_IN_STEREO}, + + .outputCfg = {.accessMode = EFFECT_BUFFER_ACCESS_WRITE, + .format = AUDIO_FORMAT_PCM_FLOAT, + .bufferProvider.getBuffer = nullptr, + .bufferProvider.releaseBuffer = nullptr, + .bufferProvider.cookie = nullptr, + .mask = EFFECT_CONFIG_ALL, + .samplingRate = 48000, + .channels = AUDIO_CHANNEL_OUT_STEREO}}; }; TEST_P(libAudioHalEffectParamTest, setAndGetParam) { @@ -338,7 +353,7 @@ INSTANTIATE_TEST_SUITE_P( AudioUuid uuid = ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid( *std::get(info.param)) .value(); - std::string name = "UUID_" + uuid.toString(); + std::string name = "UUID_" + toString(uuid); std::replace_if( name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); return name; From d44311374e41a26b28db56794c9a7890a13a6972 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 042/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index bfd5f7f59a..1eb8874af1 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From 9b2183ae5d234d1138e2e8667cee8f6d0a9b1726 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 043/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index bfd5f7f59a..1eb8874af1 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From c138d20635694857754f2b7de2342089de13d556 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 044/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From a297cad0e383e863a8a286dba300cd65f2e5c04e Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 045/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From 5825299cf697df203ce42f67f741731b97f96071 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 046/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From 99d0823ca2b8275f000a437150fb8d1938b1b31a Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 047/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From c3929283feba3435c6f68942fd40b78eecaf553e Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 048/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From d5c9058168fa459a1012262c82b20154baa5c929 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 049/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From c4df8d8956b4a1ddb68ec922f0b0f5ca261aa503 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 6 Jul 2023 08:41:56 +0000 Subject: [PATCH 050/148] Fix Segv on unknown address error flagged by fuzzer test. The error is thrown when the destructor tries to free pointer memory. This is happening for cases where the pointer was not initialized. Initializing it to a default value fixes the error. Bug: 245135112 Test: Build mtp_host_property_fuzzer and run on the target device Change-Id: I255cd68b7641e96ac47ab81479b9b46b78c15580 Merged-In: I255cd68b7641e96ac47ab81479b9b46b78c15580 (cherry picked from commit 3afa6e80e8568fe63f893fa354bc79ef91d3dcc0) --- media/mtp/MtpProperty.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h index 36d736065f..2bdbfd3262 100644 --- a/media/mtp/MtpProperty.h +++ b/media/mtp/MtpProperty.h @@ -26,6 +26,9 @@ namespace android { class MtpDataPacket; struct MtpPropertyValue { + // pointer str initialized to NULL so that free operation + // is not called for pre-assigned value + MtpPropertyValue() : str (NULL) {} union { int8_t i8; uint8_t u8; From 8433a6f43eb0917d331d22291508c9866712254f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Julliard?= Date: Mon, 10 Jul 2023 14:07:10 -0700 Subject: [PATCH 051/148] Remove logging when metadata tag can't be found. This logging is expensive when it happens at 30fps (measured at around 0.5 mW per such message @30fps). Furthermore, no such logging happens in the SDK when a tag can't be found, so this is simply aligning the NDK's behavior with the SDK's. Bug: 290694535 Test: built and confirmed power reduction. Change-Id: I2b5397aa79fb176d90678a30550af08872b29a20 --- camera/ndk/impl/ACameraMetadata.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp index 4995dc45da..1fd4a864b6 100644 --- a/camera/ndk/impl/ACameraMetadata.cpp +++ b/camera/ndk/impl/ACameraMetadata.cpp @@ -400,7 +400,6 @@ ACameraMetadata::getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) camera_metadata_ro_entry rawEntry = static_cast(mData.get())->find(tag); if (rawEntry.count == 0) { - ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag); return ACAMERA_ERROR_METADATA_NOT_FOUND; } entry->tag = tag; From 0765e02674f741c1c3b6fd5a514ad100cd4fb2f6 Mon Sep 17 00:00:00 2001 From: Ravneet Date: Tue, 11 Jul 2023 19:26:38 +0000 Subject: [PATCH 052/148] Camera: Fix FD leak - To prevent leaking of duplicated FD, use original FD in syncTimestampToDisplayLocked and duplicate when used Test: CTS test Bug: 290155485 Change-Id: I8d4f4b623aec9e731862f9789f940e339edd10dc --- .../libcameraservice/device3/Camera3OutputStream.cpp | 8 ++++---- .../camera/libcameraservice/device3/Camera3OutputStream.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp index a387064b82..aaf5d8d9e7 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp +++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp @@ -486,7 +486,7 @@ status_t Camera3OutputStream::returnBufferCheckedLocked( bufferDeferred = true; } else { nsecs_t presentTime = mSyncToDisplay ? - syncTimestampToDisplayLocked(captureTime, releaseFence->dup()) : captureTime; + syncTimestampToDisplayLocked(captureTime, releaseFence) : captureTime; setTransform(transform, true/*mayChangeMirror*/); res = native_window_set_buffers_timestamp(mConsumer.get(), presentTime); @@ -1410,7 +1410,7 @@ void Camera3OutputStream::returnPrefetchedBuffersLocked() { } } -nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t, int releaseFence) { +nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t, sp releaseFence) { nsecs_t currentTime = systemTime(); if (!mFixedFps) { mLastCaptureTime = t; @@ -1458,8 +1458,8 @@ nsecs_t Camera3OutputStream::syncTimestampToDisplayLocked(nsecs_t t, int release mRefVsyncData = vsyncEventData; mReferenceCaptureTime = t; mReferenceArrivalTime = currentTime; - if (releaseFence != -1) { - mReferenceFrameFence = new Fence(releaseFence); + if (releaseFence->isValid()) { + mReferenceFrameFence = new Fence(releaseFence->dup()); } else { mFenceSignalOffset = 0; } diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h index 1435081cb1..ebd579745e 100644 --- a/services/camera/libcameraservice/device3/Camera3OutputStream.h +++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h @@ -446,7 +446,7 @@ class Camera3OutputStream : static constexpr nsecs_t kTimelineThresholdNs = 1000000LL; // 1 millisecond static constexpr float kMaxIntervalRatioDeviation = 0.05f; static constexpr int kMaxTimelines = 2; - nsecs_t syncTimestampToDisplayLocked(nsecs_t t, int releaseFence); + nsecs_t syncTimestampToDisplayLocked(nsecs_t t, sp releaseFence); // In case of fence being used sp mReferenceFrameFence; From d42a8ea948763e858c7a75d8883a749113fa3e42 Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Mon, 10 Jul 2023 10:18:35 -0600 Subject: [PATCH 053/148] Fix delay used when polling for rendered buffers If a desired render time earlier than the current system clock time is provided to MediaCodec::releaseOutputBuffer, it is likely that the onFrameRendered callback will be dropped. This is because the code that sets the delay for polling for rendered buffers always assumes the desired render time is in the future. This is not necessarily true if apps choose to still specify a desired render time as soon as possible to render a buffer that has been delayed due to decoding or network problems, rather than using MediaCodec::releaseOutputBuffer that has no desired render time parameter. Bug: 288044725 Test: atest DecoderRenderTest Change-Id: I40bb693405d2338cf1b43d9a0d8545386595e8ed --- media/libstagefright/MediaCodec.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index e0ebc1143c..1a8597f7d9 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -6060,7 +6060,9 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp &msg) { // presentation timestamp is used instead, which almost certainly occurs in the past, // since it's almost always a zero-based offset from the start of the stream. In these // scenarios, we expect the frame to be rendered with no delay. - int64_t delayUs = noRenderTime ? 0 : renderTimeNs / 1000 - ALooper::GetNowUs(); + int64_t nowUs = ALooper::GetNowUs(); + int64_t renderTimeUs = renderTimeNs / 1000; + int64_t delayUs = renderTimeUs < nowUs ? 0 : renderTimeUs - nowUs; delayUs += 100 * 1000; /* 100ms in microseconds */ status_t err = mMsgPollForRenderedBuffers->postUnique(/* token= */ mMsgPollForRenderedBuffers, From cbf1eb34b18d70b1581e036446150a6233fd75d1 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 29 Jun 2023 23:29:47 +0000 Subject: [PATCH 054/148] Fix LOG_TAG in several files of libeffects Bug: 271500140 Test: m libbundleaidl; m libreverbaidl Merged-In: I0b2c0b78bf10ecbe752a5dfce230f19349582264 Change-Id: I0b2c0b78bf10ecbe752a5dfce230f19349582264 (cherry picked from commit 79b253db5e56bb6e8f1d484b579ebc0be7262ae8) --- .../lvm/wrapper/Aidl/EffectBundleAidl.cpp | 14 +++++++------- .../lvm/wrapper/Reverb/aidl/EffectReverb.cpp | 13 +++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp index eb7ab1a2af..3148d36361 100644 --- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp +++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp @@ -14,21 +14,21 @@ * limitations under the License. */ -#include "BundleTypes.h" -#define LOG_TAG "EffectBundleAidl" -#include #include +#include #include +#define LOG_TAG "EffectBundleAidl" -#include -#include #include #include #include +#include +#include +#include +#include +#include "BundleTypes.h" #include "EffectBundleAidl.h" -#include -#include using aidl::android::hardware::audio::effect::getEffectImplUuidBassBoostBundle; using aidl::android::hardware::audio::effect::Descriptor; diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp index 73141b677f..b49d109819 100644 --- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp @@ -14,20 +14,21 @@ * limitations under the License. */ -#include "ReverbTypes.h" -#define LOG_TAG "EffectReverb" -#include #include +#include #include -#include -#include +#define LOG_TAG "EffectReverb" + #include #include #include +#include +#include +#include #include "EffectReverb.h" -#include +#include "ReverbTypes.h" using aidl::android::hardware::audio::effect::Descriptor; using aidl::android::hardware::audio::effect::EffectReverb; From 811b520a87918b95d3d4a303f0cfb4afa7bb1283 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 13 Jul 2023 23:23:35 +0000 Subject: [PATCH 055/148] Fix Visualizer capture size reset in wraparound Bug: 271500140 Test: Youtube with 3rd part Visualizer Merged-In: I82bda04b7d00c76f74f8082f78a54ef81152e908 Change-Id: I82bda04b7d00c76f74f8082f78a54ef81152e908 (cherry picked from commit b1ea0df0f05d99747e95b5c2a3b9f2d5ecc6e646) --- media/libeffects/visualizer/aidl/VisualizerContext.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp index 5d0d08d2dc..a1726ad5fb 100644 --- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp +++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp @@ -223,8 +223,7 @@ std::vector VisualizerContext::capture() { deltaSamples = kMaxCaptureBufSize; } - int32_t capturePoint; - //capturePoint = (int32_t)mCaptureIdx - deltaSamples; + int32_t capturePoint, captureSamples = mCaptureSamples; __builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint); // a negative capturePoint means we wrap the buffer. if (capturePoint < 0) { @@ -232,13 +231,14 @@ std::vector VisualizerContext::capture() { if (size > mCaptureSamples) { size = mCaptureSamples; } + // first part of two stages copy, capture to the end of buffer and reset the size/point result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint], &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]); - mCaptureSamples -= size; + captureSamples -= size; capturePoint = 0; } result.insert(result.end(), &mCaptureBuf[capturePoint], - &mCaptureBuf[capturePoint + mCaptureSamples]); + &mCaptureBuf[capturePoint + captureSamples]); mLastCaptureIdx = mCaptureIdx; return result; } From b1aaf9a71ffc75ea7acab67287d25fa05daefb5b Mon Sep 17 00:00:00 2001 From: Kwangkyu Park Date: Sat, 8 Jul 2023 00:42:03 +0900 Subject: [PATCH 056/148] Camera: Prevent simultenous HAL initialization If camera client fails to initialize then connectHelper just return error code without explicitly disconnect the client. This could cause the HAL to be initialized between the conflicting devies, if multiple camera connect attempt is invoked simultaneously. This patch will prevent the situation by explicitly disconnecting the client before returning the error code. Bug: 290325991 Test: Manual test with the OEM application Change-Id: I2d7a14c01ed5ae6e0f4335f1f0be5742c637b8ee --- services/camera/libcameraservice/CameraService.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 668a51ae6d..d1351cf64f 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -2040,6 +2040,9 @@ Status CameraService::connectHelper(const sp& cameraCb, const String8& if (err != OK) { ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__); // Errors could be from the HAL module open call or from AppOpsManager + mServiceLock.unlock(); + client->disconnect(); + mServiceLock.lock(); switch(err) { case BAD_VALUE: return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, From e8898de1045418a3ed738dc406cd204340ac4409 Mon Sep 17 00:00:00 2001 From: mtk12103 Date: Fri, 9 Jun 2023 14:00:55 +0800 Subject: [PATCH 057/148] Add buffer usage for more consumers The consumer of a video decoder output could be display, GPU, or encoders. Add checks for encoders for pixel format support test. Bug: 282895340 Test: android.mediav2.cts.CodecEncoderSurfaceTest (cherry picked from https://android-review.googlesource.com/q/commit:a438ca0a0e56f958994c6c0c1358c8cf9610748a) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:06e466b209cf3fdd74aa65bd1098e9f0adac9a02) Merged-In: Iebc17309e04a84d08f137f38e561b83a58ecb642 Change-Id: Iebc17309e04a84d08f137f38e561b83a58ecb642 --- .../sfplugin/utils/Codec2CommonUtils.cpp | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp index 332d3ac385..bb6c1b86c3 100644 --- a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp +++ b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp @@ -82,6 +82,7 @@ bool isHalPixelFormatSupported(AHardwareBuffer_Format format) { return false; } + // Default scenario --- the consumer is display or GPU const AHardwareBuffer_Desc desc = { .width = 320, .height = 240, @@ -96,7 +97,40 @@ bool isHalPixelFormatSupported(AHardwareBuffer_Format format) { .rfu1 = 0, }; - return AHardwareBuffer_isSupported(&desc); + // The consumer is a HW encoder + const AHardwareBuffer_Desc descHwEncoder = { + .width = 320, + .height = 240, + .format = format, + .layers = 1, + .usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | + AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | + AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY | + AHARDWAREBUFFER_USAGE_VIDEO_ENCODE, + .stride = 0, + .rfu0 = 0, + .rfu1 = 0, + }; + + // The consumer is a SW encoder + const AHardwareBuffer_Desc descSwEncoder = { + .width = 320, + .height = 240, + .format = format, + .layers = 1, + .usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | + AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN | + AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY, + .stride = 0, + .rfu0 = 0, + .rfu1 = 0, + }; + + return AHardwareBuffer_isSupported(&desc) + && AHardwareBuffer_isSupported(&descHwEncoder) + && AHardwareBuffer_isSupported(&descSwEncoder); } } // namespace android From f5cd81160b12effa3b8a3b1058668dbbb70359b8 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Tue, 18 Jul 2023 13:55:34 -0700 Subject: [PATCH 058/148] libaudiohal@aidl: Process telephony parameters Add processing and conversion into AIDL for AUDIO_PARAMETER_KEY_TTY_MODE and AUDIO_PARAMETER_KEY_HAC. Bug: 291411017 Test: m (cherry picked from https://android-review.googlesource.com/q/commit:b9a81314fdbd258f256dd1f1d2443c434aa40ecd) Merged-In: I097fab057f0ba4eacb5c0455f8158492797391bc Change-Id: I097fab057f0ba4eacb5c0455f8158492797391bc --- media/libaudiohal/impl/DeviceHalAidl.cpp | 49 +++++++++++++++++++ media/libaudiohal/impl/DeviceHalAidl.h | 1 + media/libmediahelper/AudioParameter.cpp | 10 ++++ .../include/media/AudioParameter.h | 16 ++++++ 4 files changed, 76 insertions(+) diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp index c7d7f69a15..99e3565862 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.cpp +++ b/media/libaudiohal/impl/DeviceHalAidl.cpp @@ -293,6 +293,9 @@ status_t DeviceHalAidl::setParameters(const String8& kvPairs) { if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) { ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status); } + if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) { + ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status); + } return parseAndSetVendorParameters(mVendorExt, mModule, parameters); } @@ -1370,6 +1373,52 @@ status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter ¶mete return OK; } +status_t DeviceHalAidl::filterAndUpdateTelephonyParameters(AudioParameter ¶meters) { + TIME_CHECK(); + using TtyMode = ITelephony::TelecomConfig::TtyMode; + ITelephony::TelecomConfig telConfig; + (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter( + parameters, String8(AudioParameter::keyTtyMode), + [&telConfig](const String8& mode) { + if (mode == AudioParameter::valueTtyModeOff) { + telConfig.ttyMode = TtyMode::OFF; + return OK; + } else if (mode == AudioParameter::valueTtyModeFull) { + telConfig.ttyMode = TtyMode::FULL; + return OK; + } else if (mode == AudioParameter::valueTtyModeHco) { + telConfig.ttyMode = TtyMode::HCO; + return OK; + } else if (mode == AudioParameter::valueTtyModeVco) { + telConfig.ttyMode = TtyMode::VCO; + return OK; + } + ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"", + AudioParameter::keyTtyMode, mode.c_str()); + return BAD_VALUE; + })); + (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter( + parameters, String8(AudioParameter::keyHacSetting), + [&telConfig](const String8& onOrOff) { + if (onOrOff == AudioParameter::valueHacOn) { + telConfig.isHacEnabled = Boolean{ .value = true }; + return OK; + } else if (onOrOff == AudioParameter::valueHacOff) { + telConfig.isHacEnabled = Boolean{ .value = false }; + return OK; + } + ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"", + AudioParameter::keyHacSetting, onOrOff.c_str()); + return BAD_VALUE; + })); + if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) { + ITelephony::TelecomConfig newTelConfig; + return statusTFromBinderStatus( + mTelephony->setTelecomConfig(telConfig, &newTelConfig)); + } + return OK; +} + status_t DeviceHalAidl::findOrCreatePatch( const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) { std::set sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(), diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h index 6566de13f6..6b34bf42aa 100644 --- a/media/libaudiohal/impl/DeviceHalAidl.h +++ b/media/libaudiohal/impl/DeviceHalAidl.h @@ -224,6 +224,7 @@ class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl, status_t filterAndUpdateBtLeParameters(AudioParameter ¶meters); status_t filterAndUpdateBtScoParameters(AudioParameter ¶meters); status_t filterAndUpdateScreenParameters(AudioParameter ¶meters); + status_t filterAndUpdateTelephonyParameters(AudioParameter ¶meters); status_t findOrCreatePatch( const std::set& sourcePortConfigIds, const std::set& sinkPortConfigIds, diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp index 3832e90885..816396e743 100644 --- a/media/libmediahelper/AudioParameter.cpp +++ b/media/libmediahelper/AudioParameter.cpp @@ -43,6 +43,16 @@ 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; +#ifndef __ANDROID_VNDK__ +const char * const AudioParameter::keyTtyMode = AUDIO_PARAMETER_KEY_TTY_MODE; +const char * const AudioParameter::valueTtyModeOff = AUDIO_PARAMETER_VALUE_TTY_OFF; +const char * const AudioParameter::valueTtyModeFull = AUDIO_PARAMETER_VALUE_TTY_FULL; +const char * const AudioParameter::valueTtyModeHco = AUDIO_PARAMETER_VALUE_TTY_HCO; +const char * const AudioParameter::valueTtyModeVco = AUDIO_PARAMETER_VALUE_TTY_VCO; +const char * const AudioParameter::keyHacSetting = AUDIO_PARAMETER_KEY_HAC; +const char * const AudioParameter::valueHacOff = AUDIO_PARAMETER_VALUE_HAC_OFF; +const char * const AudioParameter::valueHacOn = AUDIO_PARAMETER_VALUE_HAC_ON; +#endif // __ANDROID_VNDK__ 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; diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h index 3eee854f74..a4abd062b7 100644 --- a/media/libmediahelper/include/media/AudioParameter.h +++ b/media/libmediahelper/include/media/AudioParameter.h @@ -69,6 +69,22 @@ class AudioParameter { static const char * const keyBtHfpSamplingRate; static const char * const keyBtHfpVolume; +#ifndef __ANDROID_VNDK__ + // These static fields are not used by vendor code, they were added to make + // the framework code consistent. There is no plan to expose them to vendors + // because they were used by HIDL get/setParameters interface which does not + // exist in the AIDL HAL interface. + static const char * const keyTtyMode; + static const char * const valueTtyModeOff; + static const char * const valueTtyModeFull; + static const char * const valueTtyModeHco; + static const char * const valueTtyModeVco; + + static const char * const keyHacSetting; + static const char * const valueHacOff; + static const char * const valueHacOn; +#endif // __ANDROID_VNDK__ + // keyHwAvSync: get HW synchronization source identifier from a device // keyMonoOutput: Enable mono audio playback // keyStreamHwAvSync: set HW synchronization source identifier on a stream From fdf42d7634823a437a66fa7e2f26293c9f297903 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 13 Jul 2023 23:25:38 +0000 Subject: [PATCH 059/148] EffectProxy return the active sub-effect descriptor Bug: 271500140 Test: Youtube Music on Panther Change-Id: I13d92f9d8345e7d38e886adaf82f4e67eebea5a8 Merged-In: I13d92f9d8345e7d38e886adaf82f4e67eebea5a8 --- media/libaudiohal/impl/EffectProxy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index f83d47998c..6b042d52d8 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -133,8 +133,8 @@ ndk::ScopedAStatus EffectProxy::close() { } ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) { - desc->common = mDescriptorCommon; - desc->capability = mSubEffects[mActiveSubIdx].descriptor.capability; + *desc = mSubEffects[mActiveSubIdx].descriptor; + desc->common.id.uuid = desc->common.id.proxy.value(); return ndk::ScopedAStatus::ok(); } @@ -168,7 +168,7 @@ Descriptor::Common EffectProxy::buildDescriptorCommon( // same as HIDL EffectProxy flags common.flags.type = Flags::Type::INSERT; common.flags.insert = Flags::Insert::LAST; - common.flags.volume = Flags::Volume::CTRL; + common.flags.volume = Flags::Volume::NONE; // set indication if any sub-effect indication was set common.flags.offloadIndication |= desc.common.flags.offloadIndication; From b09f47083e088c721fa7f1f28fecb1f5bf075e4f Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 11 Jul 2023 18:10:18 +0000 Subject: [PATCH 060/148] Update offload ioHandle to effects Bug: 271500140 Test: Enavble AIDL Test: atest EffectProxyTest Change-Id: I3705b3bfed33caf139dadbff9871be34b7ee906e Merged-In: I3705b3bfed33caf139dadbff9871be34b7ee906e --- .../impl/EffectConversionHelperAidl.cpp | 11 +++-- media/libaudiohal/impl/EffectProxy.cpp | 11 +++-- media/libaudiohal/tests/EffectProxy_test.cpp | 43 +++++++++---------- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp index 72aa7d86e6..049c3585c6 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp @@ -209,12 +209,12 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi mEffect->close(); return status; } - mCommon = common; } else if (mCommon != common) { ALOGI("%s at state %s, setParameter", __func__, android::internal::ToString(state).c_str()); - Parameter aidlParam = UNION_MAKE(Parameter, common, mCommon); + Parameter aidlParam = UNION_MAKE(Parameter, common, common); RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); } + mCommon = common; return *static_cast(pReplyData) = OK; } @@ -352,9 +352,14 @@ status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const vo if (mIsProxyEffect) { ALOGI("%s offload param offload %s ioHandle %d", __func__, offload->isOffload ? "true" : "false", offload->ioHandle); - mCommon.ioHandle = offload->ioHandle; const auto& effectProxy = std::static_pointer_cast(mEffect); RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(effectProxy->setOffloadParam(offload))); + if (mCommon.ioHandle != offload->ioHandle) { + ALOGI("%s ioHandle update [%d to %d]", __func__, mCommon.ioHandle, offload->ioHandle); + mCommon.ioHandle = offload->ioHandle; + Parameter aidlParam = UNION_MAKE(Parameter, common, mCommon); + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); + } // update FMQs if the effect instance already open if (State state; effectProxy->getState(&state).isOk() && state != State::INIT) { mStatusQ = effectProxy->getStatusMQ(); diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index 6b042d52d8..cb5b4b9544 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #define LOG_TAG "EffectProxy" @@ -90,12 +91,16 @@ ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* of "noActiveEffctFound"); } - mActiveSubIdx = std::distance(mSubEffects.begin(), itor); - ALOGV("%s: active %soffload sub-effect %zu descriptor: %s", __func__, + const size_t newIndex = std::distance(mSubEffects.begin(), itor); + mActiveSubIdx = newIndex; + + ALOGI("%s: active %soffload sub-effect %zu descriptor: %s", __func__, offload->isOffload ? "" : "non-", mActiveSubIdx, ::android::audio::utils::toString(mSubEffects[mActiveSubIdx].descriptor.common.id.uuid) .c_str()); - return ndk::ScopedAStatus::ok(); + return runWithAllSubEffects([&](std::shared_ptr& effect) { + return effect->setParameter(Parameter::make(offload->isOffload)); + }); } // EffectProxy go over sub-effects and call IEffect interfaces diff --git a/media/libaudiohal/tests/EffectProxy_test.cpp b/media/libaudiohal/tests/EffectProxy_test.cpp index 8668e85bcf..2953b0ab47 100644 --- a/media/libaudiohal/tests/EffectProxy_test.cpp +++ b/media/libaudiohal/tests/EffectProxy_test.cpp @@ -53,7 +53,9 @@ class EffectProxyTest : public testing::Test { void SetUp() override { auto serviceName = android::getAidlHalInstanceNames(IFactory::descriptor); // only unit test with the first one in case more than one EffectFactory service exist - ASSERT_NE(0ul, serviceName.size()); + if (0ul == serviceName.size()) { + GTEST_SKIP() << "EffectFactory not available on device, skipping"; + } mFactory = IFactory::fromBinder( ndk::SpAIBinder(AServiceManager_waitForService(serviceName[0].c_str()))); ASSERT_NE(nullptr, mFactory); @@ -157,6 +159,7 @@ TEST_F(EffectProxyTest, setOffloadParam) { effect_offload_param_t offloadParam{false, 0}; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); offloadParam.isOffload = true; + offloadParam.ioHandle++; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->close().isOk()); EXPECT_TRUE(proxy->destroy().isOk()); @@ -189,21 +192,21 @@ TEST_F(EffectProxyTest, normalSequency) { Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; Parameter::VolumeStereo volumeStereo({.left = .1f, .right = -0.8f}); - Parameter param = Parameter::make(volumeStereo); - Parameter::Id id = Parameter::Id::make(Parameter::volumeStereo); + Parameter expect = Parameter::make(volumeStereo); + const Parameter::Id id = Parameter::Id::make(Parameter::volumeStereo); State state; for (const auto& itor : proxyMap) { - Parameter expect; + Parameter getParam = Parameter::make(true); auto& proxy = std::get(itor.second); effect_offload_param_t offloadParam{true, 0}; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); - EXPECT_TRUE(proxy->setParameter(param).isOk()); - EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); - EXPECT_EQ(expect, param) << " EXPECTED: " << expect.toString() - << "\nACTUAL: " << param.toString(); + EXPECT_TRUE(proxy->setParameter(expect).isOk()); + EXPECT_TRUE(proxy->getParameter(id, &getParam).isOk()); + EXPECT_EQ(expect, getParam) + << " EXPECTED: " << expect.toString() << "\nACTUAL: " << getParam.toString(); EXPECT_TRUE(proxy->command(CommandId::START).isOk()); EXPECT_TRUE(proxy->getState(&state).isOk()); @@ -225,25 +228,25 @@ TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) { Parameter::Common common = createParamCommon(); IEffect::OpenEffectReturn ret; Parameter::VolumeStereo volumeStereo({.left = .5f, .right = .8f}); - Parameter param = Parameter::make(volumeStereo); - Parameter::Id id = Parameter::Id::make(Parameter::volumeStereo); + Parameter expect = Parameter::make(volumeStereo); + const Parameter::Id id = Parameter::Id::make(Parameter::volumeStereo); for (const auto& itor : proxyMap) { - Parameter expect; + Parameter getParam = Parameter::make(true); auto& proxy = std::get(itor.second); EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk()); - EXPECT_TRUE(proxy->setParameter(param).isOk()); - EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); - EXPECT_EQ(expect, param); + EXPECT_TRUE(proxy->setParameter(expect).isOk()); + EXPECT_TRUE(proxy->getParameter(id, &getParam).isOk()); + EXPECT_EQ(expect, getParam); effect_offload_param_t offloadParam{false, 0}; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); - EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); - EXPECT_EQ(expect, param); + EXPECT_TRUE(proxy->getParameter(id, &getParam).isOk()); + EXPECT_EQ(expect, getParam); offloadParam.isOffload = true; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); - EXPECT_TRUE(proxy->getParameter(id, &expect).isOk()); - EXPECT_EQ(expect, param); + EXPECT_TRUE(proxy->getParameter(id, &getParam).isOk()); + EXPECT_EQ(expect, getParam); EXPECT_TRUE(proxy->close().isOk()); EXPECT_TRUE(proxy->destroy().isOk()); @@ -271,13 +274,9 @@ TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) { effect_offload_param_t offloadParam{false, 0}; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); - EXPECT_TRUE(proxy->getState(&state).isOk()); - EXPECT_EQ(State::PROCESSING, state); offloadParam.isOffload = true; EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk()); - EXPECT_TRUE(proxy->getState(&state).isOk()); - EXPECT_EQ(State::PROCESSING, state); EXPECT_TRUE(proxy->command(CommandId::STOP).isOk()); EXPECT_TRUE(proxy->getState(&state).isOk()); From df6d0502a2aadd17a0dc39439ac9108e21d349c0 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Wed, 26 Jul 2023 22:39:33 +0000 Subject: [PATCH 061/148] Camera: Handle single logical requests when notifying requests Consider cases where clients pass single logical capture requests to physical outputs and notify request frame number listeners accordingly. Bug: 292144312 Test: Camera CTS Change-Id: I3a44cc9a7eaa5b2107f494bddb5e80706eec2bfd Merged-In: I3a44cc9a7eaa5b2107f494bddb5e80706eec2bfd --- services/camera/libcameraservice/device3/Camera3Device.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 61c3298403..e5228d315c 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -4010,8 +4010,11 @@ status_t Camera3Device::RequestThread::prepareHalRequests() { sp parent = mParent.promote(); if (parent != nullptr) { const String8& streamCameraId = outputStream->getPhysicalCameraId(); + // Consider the case where clients are sending a single logical camera request + // to physical output/outputs + bool singleRequest = captureRequest->mSettingsList.size() == 1; for (const auto& settings : captureRequest->mSettingsList) { - if ((streamCameraId.isEmpty() && + if (((streamCameraId.isEmpty() || singleRequest) && parent->getId() == settings.cameraId.c_str()) || streamCameraId == settings.cameraId.c_str()) { outputStream->fireBufferRequestForFrameNumber( From 03100eda3fbe3278157d0753e0589af411db216d Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Mon, 31 Jul 2023 15:46:18 -0700 Subject: [PATCH 062/148] camera2: Fix links in SENSOR_PIXEL_MODE docs Bug: 290687960 Test: Inspect make doc-comment-check-docs output Change-Id: I9baf1a9d6d12623c3a1b400ea205d062b010e237 Signed-off-by: Jayant Chowdhary --- camera/ndk/include/camera/NdkCameraMetadataTags.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index bd679e567f..af00e55e4c 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -5384,7 +5384,7 @@ typedef enum acamera_metadata_tag { * CameraMetadata#SENSOR_PIXEL_MODE_DEFAULT mode. * They can be queried through * CameraCharacteristics#get with - * CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION). + * CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION. * Unless reported by both * StreamConfigurationMaps, the outputs from * android.scaler.streamConfigurationMapMaximumResolution and @@ -5399,13 +5399,12 @@ typedef enum acamera_metadata_tag { *
    *
  • *

    The mandatory stream combinations listed in - * mandatoryMaximumResolutionStreamCombinations - * would not apply.

    + * android.scaler.mandatoryMaximumResolutionStreamCombinations would not apply.

    *
  • *
  • *

    The bayer pattern of {@code RAW} streams when * CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION - * is selected will be the one listed in binningFactor.

    + * is selected will be the one listed in ACAMERA_SENSOR_INFO_BINNING_FACTOR.

    *
  • *
  • *

    The following keys will always be present:

    @@ -5419,6 +5418,7 @@ typedef enum acamera_metadata_tag { *
* * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION + * @see ACAMERA_SENSOR_INFO_BINNING_FACTOR * @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION */ From 9dd5eda005e08fff09332a61e66755d473dba73c Mon Sep 17 00:00:00 2001 From: Kwangkyu Park Date: Tue, 20 Jun 2023 21:12:06 +0900 Subject: [PATCH 063/148] Camera: Handling out-of-order request id For the API1 path, the request id is assumed to be in order when syncing with the device for the request to apply. This is not always the case, as errors can cause out-of-order and this can cause delay in the API1 path. This change will address this by maintaining the request id list. Bug: 288065275 Test: Manual test with the app using API1, atest -c -d cts/tests/camera/src/android/hardware/cts/ Change-Id: Iaacf349408c751e178173d6e03d41f1335749c27 --- .../libcameraservice/api1/Camera2Client.cpp | 16 +++++++++++----- .../camera/libcameraservice/api1/Camera2Client.h | 10 +++------- .../libcameraservice/device3/Camera3Device.cpp | 9 ++++++++- .../libcameraservice/device3/Camera3Device.h | 1 + 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index 8348cd9a04..5b5892a088 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -70,7 +70,9 @@ Camera2Client::Camera2Client(const sp& cameraService, cameraDeviceId, api1CameraId, cameraFacing, sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass, overrideToPortrait, /*legacyClient*/ true), - mParameters(api1CameraId, cameraFacing) + mParameters(api1CameraId, cameraFacing), + mLatestRequestIds(kMaxRequestIds), + mLatestFailedRequestIds(kMaxRequestIds) { ATRACE_CALL(); @@ -1843,7 +1845,7 @@ void Camera2Client::notifyError(int32_t errorCode, (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT == errorCode)) { Mutex::Autolock al(mLatestRequestMutex); - mLatestFailedRequestId = resultExtras.requestId; + mLatestFailedRequestIds.add(resultExtras.requestId); mLatestRequestSignal.signal(); } mCaptureSequencer->notifyError(errorCode, resultExtras); @@ -2418,7 +2420,10 @@ status_t Camera2Client::waitUntilCurrentRequestIdLocked() { status_t Camera2Client::waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout) { Mutex::Autolock l(mLatestRequestMutex); - while ((mLatestRequestId != requestId) && (mLatestFailedRequestId != requestId)) { + while ((std::find(mLatestRequestIds.begin(), mLatestRequestIds.end(), requestId) == + mLatestRequestIds.end()) && + (std::find(mLatestFailedRequestIds.begin(), mLatestFailedRequestIds.end(), requestId) == + mLatestFailedRequestIds.end())) { nsecs_t startTime = systemTime(); auto res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout); @@ -2427,13 +2432,14 @@ status_t Camera2Client::waitUntilRequestIdApplied(int32_t requestId, nsecs_t tim timeout -= (systemTime() - startTime); } - return (mLatestRequestId == requestId) ? OK : DEAD_OBJECT; + return (std::find(mLatestRequestIds.begin(), mLatestRequestIds.end(), requestId) != + mLatestRequestIds.end()) ? OK : DEAD_OBJECT; } void Camera2Client::notifyRequestId(int32_t requestId) { Mutex::Autolock al(mLatestRequestMutex); - mLatestRequestId = requestId; + mLatestRequestIds.add(requestId); mLatestRequestSignal.signal(); } diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h index 6bdb6444bd..a7ea8234b9 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.h +++ b/services/camera/libcameraservice/api1/Camera2Client.h @@ -22,11 +22,7 @@ #include "common/Camera2ClientBase.h" #include "api1/client2/Parameters.h" #include "api1/client2/FrameProcessor.h" -//#include "api1/client2/StreamingProcessor.h" -//#include "api1/client2/JpegProcessor.h" -//#include "api1/client2/ZslProcessor.h" -//#include "api1/client2/CaptureSequencer.h" -//#include "api1/client2/CallbackProcessor.h" +#include namespace android { @@ -263,8 +259,8 @@ class Camera2Client : mutable Mutex mLatestRequestMutex; Condition mLatestRequestSignal; - int32_t mLatestRequestId = -1; - int32_t mLatestFailedRequestId = -1; + static constexpr size_t kMaxRequestIds = BufferQueueDefs::NUM_BUFFER_SLOTS; + RingBuffer mLatestRequestIds, mLatestFailedRequestIds; status_t waitUntilRequestIdApplied(int32_t requestId, nsecs_t timeout); status_t waitUntilCurrentRequestIdLocked(); }; diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 61c3298403..9b5f09fda5 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -3030,6 +3030,7 @@ Camera3Device::RequestThread::RequestThread(wp parent, mNotifyPipelineDrain(false), mFrameNumber(0), mLatestRequestId(NAME_NOT_FOUND), + mLatestFailedRequestId(NAME_NOT_FOUND), mCurrentAfTriggerId(0), mCurrentPreCaptureTriggerId(0), mRotateAndCropOverride(ANDROID_SCALER_ROTATE_AND_CROP_NONE), @@ -3281,7 +3282,7 @@ status_t Camera3Device::RequestThread::waitUntilRequestProcessed( ATRACE_CALL(); Mutex::Autolock l(mLatestRequestMutex); status_t res; - while (mLatestRequestId != requestId) { + while (mLatestRequestId != requestId && mLatestFailedRequestId != requestId) { nsecs_t startTime = systemTime(); res = mLatestRequestSignal.waitRelative(mLatestRequestMutex, timeout); @@ -4356,6 +4357,12 @@ void Camera3Device::RequestThread::cleanUpFailedRequests(bool sendRequestError) hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST, captureRequest->mResultExtras); } + { + Mutex::Autolock al(mLatestRequestMutex); + + mLatestFailedRequestId = captureRequest->mResultExtras.requestId; + mLatestRequestSignal.signal(); + } } // Remove yet-to-be submitted inflight request from inflightMap diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h index b1dd135206..aa1d55ae5a 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.h +++ b/services/camera/libcameraservice/device3/Camera3Device.h @@ -1142,6 +1142,7 @@ class Camera3Device : Condition mLatestRequestSignal; // android.request.id for latest process_capture_request int32_t mLatestRequestId; + int32_t mLatestFailedRequestId; CameraMetadata mLatestRequest; std::unordered_map mLatestPhysicalRequest; From 31c2ba0a58b27833af9ecdf3cf0cf7cf462407dd Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Tue, 1 Aug 2023 23:06:13 +0000 Subject: [PATCH 064/148] Only send data to IEffect for processing in PROCESSING state Effect instance won't be able to process data in other states Bug: 293896175 Test: Enable AIDL and test YouTube with effects enabled Change-Id: Ida968fc760a8172de4e1663a37d3cbe7a9633f64 --- media/libaudiohal/impl/EffectHalAidl.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp index e4c330970c..2d9e155a35 100644 --- a/media/libaudiohal/impl/EffectHalAidl.cpp +++ b/media/libaudiohal/impl/EffectHalAidl.cpp @@ -56,6 +56,7 @@ using ::aidl::android::aidl_utils::statusTFromBinderStatus; using ::aidl::android::hardware::audio::effect::Descriptor; using ::aidl::android::hardware::audio::effect::IEffect; using ::aidl::android::hardware::audio::effect::IFactory; +using ::aidl::android::hardware::audio::effect::State; namespace android { namespace effect { @@ -165,13 +166,20 @@ status_t EffectHalAidl::setOutBuffer(const sp& buffer) // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ status_t EffectHalAidl::process() { + State state = State::INIT; + if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() || + state != State::PROCESSING) { + ALOGI("%s skipping %s process because it's %s", __func__, mDesc.common.name.c_str(), + mConversion->isBypassing() + ? "bypassing" + : aidl::android::hardware::audio::effect::toString(state).c_str()); + return OK; + } + auto statusQ = mConversion->getStatusMQ(); auto inputQ = mConversion->getInputMQ(); auto outputQ = mConversion->getOutputMQ(); auto efGroup = mConversion->getEventFlagGroup(); - if (mConversion->isBypassing()) { - return OK; - } if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ || !outputQ->isValid() || !efGroup) { ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__, From a3131f2addfea1bfc28dfd2be50f4556d494ef37 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 29 Jun 2023 22:50:31 -0700 Subject: [PATCH 065/148] codec2_vndk: don't spin during sync variable locking/unlocking Removed spinning and sched_yield for the user-space locking section of lock/unlock and added comments to the code. TODO: remove the spinning code in unlock as it does not seem to be necessary. Bug: 287432155 (cherry picked from https://android-review.googlesource.com/q/commit:6c902ef92de5fa8ae4a1c12dd67e95ac5a8e5935) Merged-In: Ie283402b3177013f918e3facb287c23a13df0550 Change-Id: Ie283402b3177013f918e3facb287c23a13df0550 --- .../codec2/vndk/platform/C2SurfaceSyncObj.cpp | 56 +++++++++++++++---- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/media/codec2/vndk/platform/C2SurfaceSyncObj.cpp b/media/codec2/vndk/platform/C2SurfaceSyncObj.cpp index d55a3d8fff..d8c2292b9c 100644 --- a/media/codec2/vndk/platform/C2SurfaceSyncObj.cpp +++ b/media/codec2/vndk/platform/C2SurfaceSyncObj.cpp @@ -114,8 +114,8 @@ C2SyncVariables *C2SurfaceSyncMemory::mem() { } namespace { - constexpr int kSpinNumForLock = 100; - constexpr int kSpinNumForUnlock = 200; + constexpr int kSpinNumForLock = 0; + constexpr int kSpinNumForUnlock = 0; enum : uint32_t { FUTEX_UNLOCKED = 0, @@ -125,32 +125,65 @@ namespace { } int C2SyncVariables::lock() { - uint32_t old; + uint32_t old = FUTEX_UNLOCKED; + + // see if we can lock uncontended immediately (if previously unlocked) + if (mLock.compare_exchange_strong(old, FUTEX_LOCKED_UNCONTENDED)) { + return 0; + } + + // spin to see if we can get it with a short wait without involving kernel for (int i = 0; i < kSpinNumForLock; i++) { - old = 0; + sched_yield(); + + old = FUTEX_UNLOCKED; if (mLock.compare_exchange_strong(old, FUTEX_LOCKED_UNCONTENDED)) { return 0; } - sched_yield(); } - if (old == FUTEX_LOCKED_UNCONTENDED) + // still locked, if other side thinks it was uncontended, now it is contended, so let them + // know that they need to wake us up. + if (old == FUTEX_LOCKED_UNCONTENDED) { old = mLock.exchange(FUTEX_LOCKED_CONTENDED); + // It is possible that the other holder released the lock at this very moment (and old + // becomes UNLOCKED), If so, we will not involve the kernel to wait for the lock to be + // released, but are still marking our lock contended (even though we are the only + // holders.) + } - while (old) { - (void) syscall(__NR_futex, &mLock, FUTEX_WAIT, FUTEX_LOCKED_CONTENDED, NULL, NULL, 0); + // while the futex is still locked by someone else + while (old != FUTEX_UNLOCKED) { + // wait until other side releases the lock (and still contented) + (void)syscall(__NR_futex, &mLock, FUTEX_WAIT, FUTEX_LOCKED_CONTENDED, NULL, NULL, 0); + // try to relock old = mLock.exchange(FUTEX_LOCKED_CONTENDED); } return 0; } int C2SyncVariables::unlock() { - if (mLock.exchange(FUTEX_UNLOCKED) == FUTEX_LOCKED_UNCONTENDED) return 0; + // TRICKY: here we assume that we are holding this lock + + // unlock the lock immediately (since we were holding it) + // If it is (still) locked uncontested, we are done (no need to involve the kernel) + if (mLock.exchange(FUTEX_UNLOCKED) == FUTEX_LOCKED_UNCONTENDED) { + return 0; + } + // We don't need to spin for unlock as here we know already we have a waiter who we need to + // wake up. This code was here in case someone just happened to lock this lock (uncontested) + // before we would wake up other waiters to avoid a syscall. It is unsure if this ever gets + // exercised or if this is the behavior we want. (Note that if this code is removed, the same + // situation is still handled in lock() by the woken up waiter that realizes that the lock is + // now taken.) for (int i = 0; i < kSpinNumForUnlock; i++) { - if (mLock.load()) { + // here we seem to check if someone relocked this lock, and if they relocked uncontested, + // we up it to contested (since there are other waiters.) + if (mLock.load() != FUTEX_UNLOCKED) { uint32_t old = FUTEX_LOCKED_UNCONTENDED; mLock.compare_exchange_strong(old, FUTEX_LOCKED_CONTENDED); + // this is always true here so we return immediately if (old) { return 0; } @@ -158,7 +191,8 @@ int C2SyncVariables::unlock() { sched_yield(); } - (void) syscall(__NR_futex, &mLock, FUTEX_WAKE, 1, NULL, NULL, 0); + // wake up one waiter + (void)syscall(__NR_futex, &mLock, FUTEX_WAKE, 1, NULL, NULL, 0); return 0; } From ff74e9d7294183287223c839e6b95b2b609a3a91 Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Thu, 20 Jul 2023 14:44:04 -0600 Subject: [PATCH 066/148] Support video render metrics for OMX Currently, no devices on Android 14 use OMX codecs, however it is expected that TV devices using OMX will upgrade to Android 14 eventually. Add support for video render metrics for these device upgrades so that we have universal video render metrics on all Android 14 devices. Bug: 286919416 Bug: 234833109 Test: atest DecoderRenderTest on ADT-3 on Android 12 Test: Play youtube videos on ADT-3 on Android 12 Change-Id: Ia22d976bc2ba423fd8cd71110b64b4715326fe55 --- media/codec2/sfplugin/CCodec.cpp | 4 +- media/libstagefright/ACodec.cpp | 207 ++++++++++-------- media/libstagefright/ACodecBufferChannel.cpp | 7 +- media/libstagefright/MediaCodec.cpp | 25 ++- .../include/ACodecBufferChannel.h | 5 +- .../include/media/stagefright/ACodec.h | 36 ++- .../include/media/stagefright/CodecBase.h | 2 +- .../media/stagefright/FrameRenderTracker.h | 106 +++++---- .../include/media/stagefright/MediaCodec.h | 3 + .../media/stagefright/RenderedFrameInfo.h | 37 ++++ 10 files changed, 254 insertions(+), 178 deletions(-) create mode 100644 media/libstagefright/include/media/stagefright/RenderedFrameInfo.h diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp index 86fd8ab29e..a75ce70367 100644 --- a/media/codec2/sfplugin/CCodec.cpp +++ b/media/codec2/sfplugin/CCodec.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include "C2OMXNode.h" @@ -672,8 +673,7 @@ class CCodecCallbackImpl : public CCodecCallback { } void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) override { - mCodec->mCallback->onOutputFramesRendered( - {RenderedFrameInfo(mediaTimeUs, renderTimeNs)}); + mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, renderTimeNs)}); } void onOutputBuffersChanged() override { diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 505775b39d..2bc8c96de1 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -632,7 +633,8 @@ std::shared_ptr ACodec::getBufferChannel() { if (!mBufferChannel) { mBufferChannel = std::make_shared( new AMessage(kWhatInputBufferFilled, this), - new AMessage(kWhatOutputBufferDrained, this)); + new AMessage(kWhatOutputBufferDrained, this), + new AMessage(kWhatPollForRenderedBuffers, this)); } return mBufferChannel; } @@ -742,6 +744,7 @@ status_t ACodec::handleSetSurface(const sp &surface) { // if we have not yet started the codec, we can simply set the native window if (mBuffers[kPortIndexInput].size() == 0) { mNativeWindow = surface; + initializeFrameTracking(); return OK; } @@ -850,6 +853,7 @@ status_t ACodec::handleSetSurface(const sp &surface) { mNativeWindow = nativeWindow; mNativeWindowUsageBits = usageBits; + initializeFrameTracking(); return OK; } @@ -960,7 +964,6 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) { BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_US; info.mFenceFd = -1; - info.mRenderInfo = NULL; info.mGraphicBuffer = NULL; info.mNewGraphicBuffer = false; @@ -1228,6 +1231,7 @@ status_t ACodec::configureOutputBuffersFromNativeWindow( *bufferCount = def.nBufferCountActual; *bufferSize = def.nBufferSize; + initializeFrameTracking(); return err; } @@ -1266,7 +1270,6 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() { info.mStatus = BufferInfo::OWNED_BY_US; info.mFenceFd = fenceFd; info.mIsReadFence = false; - info.mRenderInfo = NULL; info.mGraphicBuffer = graphicBuffer; info.mNewGraphicBuffer = false; info.mDequeuedAt = mDequeueCounter; @@ -1343,7 +1346,6 @@ status_t ACodec::allocateOutputMetadataBuffers() { BufferInfo info; info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; info.mFenceFd = -1; - info.mRenderInfo = NULL; info.mGraphicBuffer = NULL; info.mNewGraphicBuffer = false; info.mDequeuedAt = mDequeueCounter; @@ -1439,42 +1441,6 @@ status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) { return err; } -void ACodec::updateRenderInfoForDequeuedBuffer( - ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info) { - - info->mRenderInfo = - mRenderTracker.updateInfoForDequeuedBuffer( - buf, fenceFd, info - &mBuffers[kPortIndexOutput][0]); - - // check for any fences already signaled - notifyOfRenderedFrames(false /* dropIncomplete */, info->mRenderInfo); -} - -void ACodec::onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { - if (mRenderTracker.onFrameRendered(mediaTimeUs, systemNano) != OK) { - mRenderTracker.dumpRenderQueue(); - } -} - -void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Info *until) { - std::list done = - mRenderTracker.checkFencesAndGetRenderedFrames(until, dropIncomplete); - - // unlink untracked frames - for (std::list::const_iterator it = done.cbegin(); - it != done.cend(); ++it) { - ssize_t index = it->getIndex(); - if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) { - mBuffers[kPortIndexOutput][index].mRenderInfo = NULL; - } else if (index >= 0) { - // THIS SHOULD NEVER HAPPEN - ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size()); - } - } - - mCallback->onOutputFramesRendered(done); -} - void ACodec::onFirstTunnelFrameReady() { mCallback->onFirstTunnelFrameReady(); } @@ -1529,7 +1495,6 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { info->mStatus = BufferInfo::OWNED_BY_US; info->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow"); - updateRenderInfoForDequeuedBuffer(buf, fenceFd, info); return info; } } @@ -1574,18 +1539,96 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() { oldest->mNewGraphicBuffer = true; oldest->mStatus = BufferInfo::OWNED_BY_US; oldest->setWriteFence(fenceFd, "dequeueBufferFromNativeWindow for oldest"); - mRenderTracker.untrackFrame(oldest->mRenderInfo); - oldest->mRenderInfo = NULL; ALOGV("replaced oldest buffer #%u with age %u, graphicBuffer %p", (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]), mDequeueCounter - oldest->mDequeuedAt, oldest->mGraphicBuffer->handle); - - updateRenderInfoForDequeuedBuffer(buf, fenceFd, oldest); return oldest; } +void ACodec::initializeFrameTracking() { + mTrackedFrames.clear(); + + int isWindowToDisplay = 0; + mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER, + &isWindowToDisplay); + mIsWindowToDisplay = isWindowToDisplay == 1; + // No frame tracking is needed if we're not sending frames to the display + if (!mIsWindowToDisplay) { + // Return early so we don't call into SurfaceFlinger (requiring permissions) + return; + } + + int hasPresentFenceTimes = 0; + mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, + &hasPresentFenceTimes); + mHasPresentFenceTimes = hasPresentFenceTimes == 1; + if (!mHasPresentFenceTimes) { + ALOGI("Using latch times for frame rendered signals - present fences not supported"); + } + + status_t err = native_window_enable_frame_timestamps(mNativeWindow.get(), true); + if (err) { + ALOGE("Failed to enable frame timestamps (%d)", err); + } +} + +void ACodec::trackReleasedFrame(int64_t frameId, int64_t mediaTimeUs, int64_t desiredRenderTimeNs) { + // If the render time is earlier than now, then we're suggesting it should be rendered ASAP, + // so track the frame as if the desired render time is now. + int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); + if (desiredRenderTimeNs < nowNs) { + desiredRenderTimeNs = nowNs; + } + // We've just queued a frame to the surface, so keep track of it and later check to see if it is + // actually rendered. + TrackedFrame frame; + frame.id = frameId; + frame.mediaTimeUs = mediaTimeUs; + frame.desiredRenderTimeNs = desiredRenderTimeNs; + mTrackedFrames.push_back(frame); +} + +void ACodec::pollForRenderedFrames() { + std::list renderedFrameInfos; + // Scan all frames and check to see if the frames that SHOULD have been rendered by now, have, + // in fact, been rendered. + int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); + while (!mTrackedFrames.empty()) { + TrackedFrame & frame = mTrackedFrames.front(); + // Frames that should have been rendered at least 100ms in the past are checked + if (frame.desiredRenderTimeNs > nowNs - 100*1000*1000LL) { + break; + } + + status_t err; + nsecs_t latchOrPresentTimeNs = NATIVE_WINDOW_TIMESTAMP_INVALID; + err = native_window_get_frame_timestamps(mNativeWindow.get(), frame.id, + /* outRequestedPresentTime */ nullptr, /* outAcquireTime */ nullptr, + mHasPresentFenceTimes ? nullptr : &latchOrPresentTimeNs, // latch time + /* outFirstRefreshStartTime */ nullptr, /* outLastRefreshStartTime */ nullptr, + /* outGpuCompositionDoneTime */ nullptr, + mHasPresentFenceTimes ? &latchOrPresentTimeNs : nullptr, // display present time, + /* outDequeueReadyTime */ nullptr, /* outReleaseTime */ nullptr); + if (err) { + ALOGE("Failed to get frame timestamps for %lld: %d", (long long) frame.id, err); + } + // If we don't have a render time by now, then consider the frame as dropped + if (latchOrPresentTimeNs != NATIVE_WINDOW_TIMESTAMP_PENDING && + latchOrPresentTimeNs != NATIVE_WINDOW_TIMESTAMP_INVALID) { + renderedFrameInfos.push_back(RenderedFrameInfo(frame.mediaTimeUs, + latchOrPresentTimeNs)); + } + + mTrackedFrames.pop_front(); + } + + if (!renderedFrameInfos.empty()) { + mCallback->onOutputFramesRendered(renderedFrameInfos); + } +} + status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) { if (portIndex == kPortIndexInput) { mBufferChannel->setInputBufferArray({}); @@ -1661,11 +1704,6 @@ status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) { ::close(info->mFenceFd); } - if (portIndex == kPortIndexOutput) { - mRenderTracker.untrackFrame(info->mRenderInfo, i); - info->mRenderInfo = NULL; - } - // remove buffer even if mOMXNode->freeBuffer fails mBuffers[portIndex].erase(mBuffers[portIndex].begin() + i); return err; @@ -6030,22 +6068,10 @@ bool ACodec::BaseState::onOMXMessageList(const sp &msg) { sp obj; CHECK(msg->findObject("messages", &obj)); sp msgList = static_cast(obj.get()); - - bool receivedRenderedEvents = false; for (std::list>::const_iterator it = msgList->getList().cbegin(); it != msgList->getList().cend(); ++it) { (*it)->setWhat(ACodec::kWhatOMXMessageItem); mCodec->handleMessage(*it); - int32_t type; - CHECK((*it)->findInt32("type", &type)); - if (type == omx_message::FRAME_RENDERED) { - receivedRenderedEvents = true; - } - } - - if (receivedRenderedEvents) { - // NOTE: all buffers are rendered in this case - mCodec->notifyOfRenderedFrames(); } return true; } @@ -6554,15 +6580,6 @@ bool ACodec::BaseState::onOMXFillBufferDone( info->mDequeuedAt = ++mCodec->mDequeueCounter; info->mStatus = BufferInfo::OWNED_BY_US; - if (info->mRenderInfo != NULL) { - // The fence for an emptied buffer must have signaled, but there still could be queued - // or out-of-order dequeued buffers in the render queue prior to this buffer. Drop these, - // as we will soon requeue this buffer to the surface. While in theory we could still keep - // track of buffers that are requeued to the surface, it is better to add support to the - // buffer-queue to notify us of released buffers and their fences (in the future). - mCodec->notifyOfRenderedFrames(true /* dropIncomplete */); - } - // byte buffers cannot take fences, so wait for any fence now if (mCodec->mNativeWindow == NULL) { (void)mCodec->waitForFence(fenceFd, "onOMXFillBufferDone"); @@ -6769,14 +6786,6 @@ void ACodec::BaseState::onOutputBufferDrained(const sp &msg) { mCodec->mLastHdr10PlusBuffer = hdr10PlusInfo; } - // save buffers sent to the surface so we can get render time when they return - int64_t mediaTimeUs = -1; - buffer->meta()->findInt64("timeUs", &mediaTimeUs); - if (mediaTimeUs >= 0) { - mCodec->mRenderTracker.onFrameQueued( - mediaTimeUs, info->mGraphicBuffer, new Fence(::dup(info->mFenceFd))); - } - int64_t timestampNs = 0; if (!msg->findInt64("timestampNs", ×tampNs)) { // use media timestamp if client did not request a specific render timestamp @@ -6790,11 +6799,25 @@ void ACodec::BaseState::onOutputBufferDrained(const sp &msg) { err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs); ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err); + uint64_t frameId; + err = native_window_get_next_frame_id(mCodec->mNativeWindow.get(), &frameId); + info->checkReadFence("onOutputBufferDrained before queueBuffer"); err = mCodec->mNativeWindow->queueBuffer( mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd); - // TODO(b/266211548): Poll the native window for rendered buffers, since when queueing - // buffers, the frame event history delta is retrieved. + + int64_t mediaTimeUs = -1; + buffer->meta()->findInt64("timeUs", &mediaTimeUs); + if (mCodec->mIsWindowToDisplay) { + mCodec->trackReleasedFrame(frameId, mediaTimeUs, timestampNs); + mCodec->pollForRenderedFrames(); + } else { + // When the surface is an intermediate surface, onFrameRendered is triggered immediately + // when the frame is queued to the non-display surface + mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, + timestampNs)}); + } + info->mFenceFd = -1; if (err == OK) { info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW; @@ -7021,7 +7044,6 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp &msg) { ++mCodec->mNodeGeneration; mCodec->mComponentName = componentName; - mCodec->mRenderTracker.setComponentName(componentName); mCodec->mFlags = 0; if (componentName.endsWith(".secure")) { @@ -7644,7 +7666,6 @@ void ACodec::ExecutingState::resume() { void ACodec::ExecutingState::stateEntered() { ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str()); - mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); mCodec->processDeferredMessages(); } @@ -7755,7 +7776,15 @@ bool ACodec::ExecutingState::onMessageReceived(const sp &msg) { mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround(); } } - return true; + handled = true; + break; + } + + case kWhatPollForRenderedBuffers: + { + mCodec->pollForRenderedFrames(); + handled = true; + break; } default: @@ -8439,7 +8468,7 @@ void ACodec::forceStateTransition(int generation) { } bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) { - mCodec->onFrameRendered(mediaTimeUs, systemNano); + mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, systemNano)}); return true; } @@ -8613,7 +8642,7 @@ void ACodec::OutputPortSettingsChangedState::stateEntered() { bool ACodec::OutputPortSettingsChangedState::onOMXFrameRendered( int64_t mediaTimeUs, nsecs_t systemNano) { - mCodec->onFrameRendered(mediaTimeUs, systemNano); + mCodec->mCallback->onOutputFramesRendered({RenderedFrameInfo(mediaTimeUs, systemNano)}); return true; } @@ -8644,10 +8673,6 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent( OMX_CommandPortEnable, kPortIndexOutput); } - // Clear the RenderQueue in which queued GraphicBuffers hold the - // actual buffer references in order to free them early. - mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); - if (err == OK) { err = mCodec->allocateBuffersOnPort(kPortIndexOutput); ALOGE_IF(err != OK, "Failed to allocate output port buffers after port " @@ -9031,8 +9056,6 @@ void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() { // the native window for rendering. Let's get those back as well. mCodec->waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs(); - mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC)); - mCodec->mCallback->onFlushCompleted(); mCodec->mPortEOS[kPortIndexInput] = diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp index 8f2bed240b..ad42813d14 100644 --- a/media/libstagefright/ACodecBufferChannel.cpp +++ b/media/libstagefright/ACodecBufferChannel.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -87,9 +88,11 @@ ACodecBufferChannel::BufferInfo::BufferInfo( } ACodecBufferChannel::ACodecBufferChannel( - const sp &inputBufferFilled, const sp &outputBufferDrained) + const sp &inputBufferFilled, const sp &outputBufferDrained, + const sp &pollForRenderedBuffers) : mInputBufferFilled(inputBufferFilled), mOutputBufferDrained(outputBufferDrained), + mPollForRenderedBuffers(pollForRenderedBuffers), mHeapSeqNum(-1) { } @@ -488,7 +491,7 @@ status_t ACodecBufferChannel::renderOutputBuffer( } void ACodecBufferChannel::pollForRenderedBuffers() { - // TODO(b/266211548): Poll the native window for rendered buffers. + mPollForRenderedBuffers->post(); } status_t ACodecBufferChannel::discardBuffer(const sp &buffer) { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 1a8597f7d9..463f212db6 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -750,7 +751,7 @@ class CodecCallback : public CodecBase::CodecCallback { const sp &outputFormat) override; virtual void onInputSurfaceDeclined(status_t err) override; virtual void onSignaledInputEOS(status_t err) override; - virtual void onOutputFramesRendered(const std::list &done) override; + virtual void onOutputFramesRendered(const std::list &done) override; virtual void onOutputBuffersChanged() override; virtual void onFirstTunnelFrameReady() override; private: @@ -859,7 +860,7 @@ void CodecCallback::onSignaledInputEOS(status_t err) { notify->post(); } -void CodecCallback::onOutputFramesRendered(const std::list &done) { +void CodecCallback::onOutputFramesRendered(const std::list &done) { sp notify(mNotify->dup()); notify->setInt32("what", kWhatOutputFramesRendered); if (MediaCodec::CreateFramesRenderedMessage(done, notify)) { @@ -5953,12 +5954,10 @@ status_t MediaCodec::handleLeftover(size_t index) { return onQueueInputBuffer(msg); } -//static -size_t MediaCodec::CreateFramesRenderedMessage( - const std::list &done, sp &msg) { +template +static size_t CreateFramesRenderedMessageInternal(const std::list &done, sp &msg) { size_t index = 0; - for (std::list::const_iterator it = done.cbegin(); - it != done.cend(); ++it) { + for (typename std::list::const_iterator it = done.cbegin(); it != done.cend(); ++it) { if (it->getRenderTimeNs() < 0) { continue; // dropped frame from tracking } @@ -5969,6 +5968,18 @@ size_t MediaCodec::CreateFramesRenderedMessage( return index; } +//static +size_t MediaCodec::CreateFramesRenderedMessage( + const std::list &done, sp &msg) { + return CreateFramesRenderedMessageInternal(done, msg); +} + +//static +size_t MediaCodec::CreateFramesRenderedMessage( + const std::list &done, sp &msg) { + return CreateFramesRenderedMessageInternal(done, msg); +} + status_t MediaCodec::onReleaseOutputBuffer(const sp &msg) { size_t index; CHECK(msg->findSize("index", &index)); diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h index 903280f106..a464504007 100644 --- a/media/libstagefright/include/ACodecBufferChannel.h +++ b/media/libstagefright/include/ACodecBufferChannel.h @@ -29,6 +29,7 @@ #include namespace android { + struct ACodec; namespace hardware { class HidlMemory; }; @@ -63,7 +64,8 @@ class ACodecBufferChannel : public BufferChannelBase { }; ACodecBufferChannel( - const sp &inputBufferFilled, const sp &outputBufferDrained); + const sp &inputBufferFilled, const sp &outputBufferDrained, + const sp &pollForRenderedBuffers); virtual ~ACodecBufferChannel(); // BufferChannelBase interface @@ -138,6 +140,7 @@ class ACodecBufferChannel : public BufferChannelBase { const sp mInputBufferFilled; const sp mOutputBufferDrained; + const sp mPollForRenderedBuffers; sp mDealer; sp mDecryptDestination; diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h index 08c791706b..88cff23281 100644 --- a/media/libstagefright/include/media/stagefright/ACodec.h +++ b/media/libstagefright/include/media/stagefright/ACodec.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -27,9 +27,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -156,6 +156,7 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { kWhatForceStateTransition = 'fstt', kWhatCheckIfStuck = 'Cstk', kWhatSubmitExtraOutputMetadataBuffer = 'sbxo', + kWhatPollForRenderedBuffers = 'pfrb', }; enum { @@ -177,6 +178,13 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { | static_cast(BufferUsage::VIDEO_DECODER), }; + struct TrackedFrame { + int64_t id; + int64_t mediaTimeUs; + int64_t desiredRenderTimeNs; + nsecs_t renderTimeNs; + }; + struct BufferInfo { enum Status { OWNED_BY_US, @@ -204,7 +212,6 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { sp mGraphicBuffer; bool mNewGraphicBuffer; int mFenceFd; - FrameRenderTracker::Info *mRenderInfo; // The following field and 4 methods are used for debugging only bool mIsReadFence; @@ -253,6 +260,8 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { bool mUsingNativeWindow; sp mNativeWindow; + bool mIsWindowToDisplay; + bool mHasPresentFenceTimes; int mNativeWindowUsageBits; android_native_rect_t mLastNativeWindowCrop; int32_t mLastNativeWindowDataSpace; @@ -267,7 +276,7 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { // format updates. This will equal to mOutputFormat until the first actual frame is received. sp mBaseOutputFormat; - FrameRenderTracker mRenderTracker; // render information for buffers rendered by ACodec + std::deque mTrackedFrames; // render information for buffers sent to a window std::vector mBuffers[2]; bool mPortEOS[2]; status_t mInputEOSResult; @@ -349,6 +358,10 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { status_t freeOutputBuffersNotOwnedByComponent(); BufferInfo *dequeueBufferFromNativeWindow(); + void initializeFrameTracking(); + void trackReleasedFrame(int64_t frameId, int64_t mediaTimeUs, int64_t desiredRenderTimeNs); + void pollForRenderedFrames(); + inline bool storingMetadataInDecodedBuffers() { return (mPortMode[kPortIndexOutput] == IOMX::kPortModeDynamicANWBuffer) && !mIsEncoder; } @@ -571,21 +584,6 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { void processDeferredMessages(); void onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); - // called when we have dequeued a buffer |buf| from the native window to track render info. - // |fenceFd| is the dequeue fence, and |info| points to the buffer info where this buffer is - // stored. - void updateRenderInfoForDequeuedBuffer( - ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info); - - // Checks to see if any frames have rendered up until |until|, and to notify client - // (MediaCodec) of rendered frames up-until the frame pointed to by |until| or the first - // unrendered frame. These frames are removed from the render queue. - // If |dropIncomplete| is true, unrendered frames up-until |until| will be dropped from the - // queue, allowing all rendered framed up till then to be notified of. - // (This will effectively clear the render queue up-until (and including) |until|.) - // If |until| is NULL, or is not in the rendered queue, this method will check all frames. - void notifyOfRenderedFrames( - bool dropIncomplete = false, FrameRenderTracker::Info *until = NULL); void onFirstTunnelFrameReady(); diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h index 916d41e3bb..90347f9672 100644 --- a/media/libstagefright/include/media/stagefright/CodecBase.h +++ b/media/libstagefright/include/media/stagefright/CodecBase.h @@ -41,7 +41,7 @@ class BufferChannelBase; struct BufferProducerWrapper; class MediaCodecBuffer; struct PersistentSurface; -struct RenderedFrameInfo; +class RenderedFrameInfo; class Surface; struct ICrypto; class IMemory; diff --git a/media/libstagefright/include/media/stagefright/FrameRenderTracker.h b/media/libstagefright/include/media/stagefright/FrameRenderTracker.h index c14755a411..cab7ecc22a 100644 --- a/media/libstagefright/include/media/stagefright/FrameRenderTracker.h +++ b/media/libstagefright/include/media/stagefright/FrameRenderTracker.h @@ -32,61 +32,59 @@ struct ANativeWindowBuffer; namespace android { -// Tracks the render information about a frame. Frames go through several states while -// the render information is tracked: -// -// 1. queued frame: mMediaTime and mGraphicBuffer are set for the frame. mFence is the -// queue fence (read fence). mIndex is negative, and mRenderTimeNs is invalid. -// Key characteristics: mFence is not NULL and mIndex is negative. -// -// 2. dequeued frame: mFence is updated with the dequeue fence (write fence). mIndex is set. -// Key characteristics: mFence is not NULL and mIndex is non-negative. mRenderTime is still -// invalid. -// -// 3. rendered frame or frame: mFence is cleared, mRenderTimeNs is set. -// Key characteristics: mFence is NULL. -// -struct RenderedFrameInfo { - // set by client during onFrameQueued or onFrameRendered - int64_t getMediaTimeUs() const { return mMediaTimeUs; } - - // -1 if frame is not yet rendered - nsecs_t getRenderTimeNs() const { return mRenderTimeNs; } - - // set by client during updateRenderInfoForDequeuedBuffer; -1 otherwise - ssize_t getIndex() const { return mIndex; } - - // creates information for a queued frame - RenderedFrameInfo(int64_t mediaTimeUs, const sp &graphicBuffer, - const sp &fence) - : mMediaTimeUs(mediaTimeUs), - mRenderTimeNs(-1), - mIndex(-1), - mGraphicBuffer(graphicBuffer), - mFence(fence) { - } - - // creates information for a frame rendered on a tunneled surface - RenderedFrameInfo(int64_t mediaTimeUs, nsecs_t renderTimeNs) - : mMediaTimeUs(mediaTimeUs), - mRenderTimeNs(renderTimeNs), - mIndex(-1), - mGraphicBuffer(NULL), - mFence(NULL) { - } - -private: - int64_t mMediaTimeUs; - nsecs_t mRenderTimeNs; - ssize_t mIndex; // to be used by client - sp mGraphicBuffer; - sp mFence; - - friend struct FrameRenderTracker; -}; - struct FrameRenderTracker { - typedef RenderedFrameInfo Info; + // Tracks the render information about a frame. Frames go through several states while + // the render information is tracked: + // + // 1. queued frame: mMediaTime and mGraphicBuffer are set for the frame. mFence is the + // queue fence (read fence). mIndex is negative, and mRenderTimeNs is invalid. + // Key characteristics: mFence is not NULL and mIndex is negative. + // + // 2. dequeued frame: mFence is updated with the dequeue fence (write fence). mIndex is set. + // Key characteristics: mFence is not NULL and mIndex is non-negative. mRenderTime is still + // invalid. + // + // 3. rendered frame or frame: mFence is cleared, mRenderTimeNs is set. + // Key characteristics: mFence is NULL. + // + struct Info { + // set by client during onFrameQueued or onFrameRendered + int64_t getMediaTimeUs() const { return mMediaTimeUs; } + + // -1 if frame is not yet rendered + nsecs_t getRenderTimeNs() const { return mRenderTimeNs; } + + // set by client during updateRenderInfoForDequeuedBuffer; -1 otherwise + ssize_t getIndex() const { return mIndex; } + + // creates information for a queued frame + Info(int64_t mediaTimeUs, const sp &graphicBuffer, + const sp &fence) + : mMediaTimeUs(mediaTimeUs), + mRenderTimeNs(-1), + mIndex(-1), + mGraphicBuffer(graphicBuffer), + mFence(fence) { + } + + // creates information for a frame rendered on a tunneled surface + Info(int64_t mediaTimeUs, nsecs_t renderTimeNs) + : mMediaTimeUs(mediaTimeUs), + mRenderTimeNs(renderTimeNs), + mIndex(-1), + mGraphicBuffer(NULL), + mFence(NULL) { + } + + private: + int64_t mMediaTimeUs; + nsecs_t mRenderTimeNs; + ssize_t mIndex; // to be used by client + sp mGraphicBuffer; + sp mFence; + + friend struct FrameRenderTracker; + }; FrameRenderTracker(); diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 52d7d3d36d..6c2a0969d2 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -64,6 +64,7 @@ class CryptoAsync; class MediaCodecBuffer; class IMemory; struct PersistentSurface; +class RenderedFrameInfo; class SoftwareRenderer; class Surface; namespace hardware { @@ -280,6 +281,8 @@ struct MediaCodec : public AHandler { // Create a MediaCodec notification message from a list of rendered or dropped render infos // by adding rendered frame information to a base notification message. Returns the number // of frames that were rendered. + static size_t CreateFramesRenderedMessage( + const std::list &done, sp &msg); static size_t CreateFramesRenderedMessage( const std::list &done, sp &msg); diff --git a/media/libstagefright/include/media/stagefright/RenderedFrameInfo.h b/media/libstagefright/include/media/stagefright/RenderedFrameInfo.h new file mode 100644 index 0000000000..4b8a58d137 --- /dev/null +++ b/media/libstagefright/include/media/stagefright/RenderedFrameInfo.h @@ -0,0 +1,37 @@ +/* + * Copyright 2015 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. + */ + +#ifndef RENDERED_FRAME_INFO_H +#define RENDERED_FRAME_INFO_H + +namespace android { + +class RenderedFrameInfo { +public: + RenderedFrameInfo(int64_t mediaTimeUs, int64_t renderTimeNs) + : mMediaTimeUs(mediaTimeUs), mRenderTimeNs(renderTimeNs) {} + + int64_t getMediaTimeUs() const { return mMediaTimeUs; } + nsecs_t getRenderTimeNs() const { return mRenderTimeNs;} + +private: + int64_t mMediaTimeUs; + nsecs_t mRenderTimeNs; +}; + +} // android + +#endif // RENDERED_FRAME_INFO_H \ No newline at end of file From 73d89318a658ece5f337c5f9c1ec1149c52eb722 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 067/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index bd6a6c679a..09eb96a00d 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -296,6 +296,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -662,6 +666,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -673,6 +682,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index fe343f74f6..ae78db2877 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -58,6 +58,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From 15b46d31e4c6073d5ca92dbb2698b126f5d13cdb Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 068/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index bd6a6c679a..09eb96a00d 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -296,6 +296,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -662,6 +666,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -673,6 +682,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index fe343f74f6..ae78db2877 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -58,6 +58,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From e376b3dd401339cf736b1f76948b2f2338a647c9 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 069/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From 7ff382cbc3895db8bef7631888778e0d3c7c47c8 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 070/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From d0645e1ca9d985acbf679ba29cc886bdd217ec55 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 071/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From 05dc1c083095ebee0faa20498153eb466082ace0 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 072/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From 05f6e7b4bc7549a3160404557e6d7077733f5eb5 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 073/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From e2c99e1e3a87368477f888f56944ec11c8d11a6e Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 074/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From 62ecc2ec5b5580986894e568c76a93774adab757 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Thu, 13 Jul 2023 09:19:08 +0000 Subject: [PATCH 075/148] Fix heap-use-after-free issue flagged by fuzzer test. A data member of class MtpFfsHandle is being accessed after the class object has been freed in the fuzzer. The method accessing the data member is running in a separate thread that gets detached from its parent. Using a conditional variable with an atomic int predicate in the close() function to ensure the detached thread's execution has completed before freeing the object fixes the issue without blocking the processing mid-way. Bug: 243381410 Test: Build mtp_handle_fuzzer and run on the target device Change-Id: I41dde165a5eba151c958b81417d9e1065af1b411 Merged-In: I41dde165a5eba151c958b81417d9e1065af1b411 (cherry picked from commit 50bf46a3f62136386548a9187a749936bda3ee8f) --- media/mtp/MtpFfsHandle.cpp | 14 ++++++++++++++ media/mtp/MtpFfsHandle.h | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp index 2ffd7759e0..ef8c9aa789 100644 --- a/media/mtp/MtpFfsHandle.cpp +++ b/media/mtp/MtpFfsHandle.cpp @@ -297,6 +297,10 @@ int MtpFfsHandle::start(bool ptp) { } void MtpFfsHandle::close() { + auto timeout = std::chrono::seconds(2); + std::unique_lock lk(m); + cv.wait_for(lk, timeout ,[this]{return child_threads==0;}); + io_destroy(mCtx); closeEndpoints(); closeConfig(); @@ -669,6 +673,11 @@ int MtpFfsHandle::sendEvent(mtp_event me) { char *temp = new char[me.length]; memcpy(temp, me.data, me.length); me.data = temp; + + std::unique_lock lk(m); + child_threads++; + lk.unlock(); + std::thread t([this, me]() { return this->doSendEvent(me); }); t.detach(); return 0; @@ -680,6 +689,11 @@ void MtpFfsHandle::doSendEvent(mtp_event me) { if (static_cast(ret) != length) PLOG(ERROR) << "Mtp error sending event thread!"; delete[] reinterpret_cast(me.data); + + std::unique_lock lk(m); + child_threads--; + lk.unlock(); + cv.notify_one(); } } // namespace android diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h index e552e03bec..51cdef0953 100644 --- a/media/mtp/MtpFfsHandle.h +++ b/media/mtp/MtpFfsHandle.h @@ -60,6 +60,10 @@ class MtpFfsHandle : public IMtpHandle { bool mCanceled; bool mBatchCancel; + std::mutex m; + std::condition_variable cv; + std::atomic child_threads{0}; + android::base::unique_fd mControl; // "in" from the host's perspective => sink for mtp server android::base::unique_fd mBulkIn; From 1401a723899766632363129265b30d433ac69c44 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 076/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index 3b298a9bf3..e4467bbfdc 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From f07ce8eb7e31db5b6186917f4eee188a39f0c2ae Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 077/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index 3b298a9bf3..e4467bbfdc 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From 38a83caefc4b5fd5aa1071bbabf0c71f49e6ac80 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 078/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From 569328a94a997a270210cea7aa10ff8918298f44 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 079/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From 28dfceb42b04c86000146bcc8731d976028c247f Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 080/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From 0c26c2f4595b58bd7a11512227eacd480c4ddcd9 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 081/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From b3768224b8c6330768c5006d50539d27a264da95 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 082/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From 56ae070c55debb8b2c691e296bded3d6e9f63518 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 083/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From 460ec203012c51a1f16a9fc75ff7bd214a87cb39 Mon Sep 17 00:00:00 2001 From: Shruti Bihani Date: Mon, 10 Jul 2023 08:53:42 +0000 Subject: [PATCH 084/148] Fix for heap buffer overflow issue flagged by fuzzer test. OOB write occurs when a value is assigned to a buffer index which is greater than the buffer size. Adding a check on buffer bounds fixes the issue. Similar checks have been added wherever applicable on other such methods of the class. Bug: 243463593 Test: Build mtp_packet_fuzzer and run on the target device Change-Id: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b Merged-In: Icd0f2307803a1a35e655bc08d9d4cca5e2b58a9b (cherry picked from commit a669e34bb8e6f0f7b5d7a35144bd342271a24712) --- media/mtp/MtpPacket.cpp | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp index f069a83b5f..5faaac2026 100644 --- a/media/mtp/MtpPacket.cpp +++ b/media/mtp/MtpPacket.cpp @@ -92,24 +92,46 @@ void MtpPacket::copyFrom(const MtpPacket& src) { } uint16_t MtpPacket::getUInt16(int offset) const { - return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + if ((unsigned long)(offset+2) <= mBufferSize) { + return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } uint32_t MtpPacket::getUInt32(int offset) const { - return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | - ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + if ((unsigned long)(offset+4) <= mBufferSize) { + return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | + ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; + } + else { + ALOGE("offset for buffer read is greater than buffer size!"); + abort(); + } } void MtpPacket::putUInt16(int offset, uint16_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + if ((unsigned long)(offset+2) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } void MtpPacket::putUInt32(int offset, uint32_t value) { - mBuffer[offset++] = (uint8_t)(value & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); - mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + if ((unsigned long)(offset+4) <= mBufferSize) { + mBuffer[offset++] = (uint8_t)(value & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); + mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); + } + else { + ALOGE("offset for buffer write is greater than buffer size!"); + } } uint16_t MtpPacket::getContainerCode() const { From d332bc8b26f592838d48b75643d6767c9b8e5c7f Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 4 Aug 2023 11:45:23 +0200 Subject: [PATCH 085/148] audio policy: fix eligibility condition for spatialization Only tracks with linear PCM audio format can be spatialized with current architecture. Bug: 290550088 Test: atest testCreateDirectAudioTracksOnlyForGetDirectProfilesForAttributes Test: atest SpatializerTest Change-Id: I5da4265eb6332541da18c0d06145bdde94873ff5 --- .../managerdefault/AudioPolicyManager.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 5d56e7d043..b17177dcb6 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -5912,22 +5912,26 @@ bool AudioPolicyManager::canBeSpatializedInt(const audio_attributes_t *attr, } } - sp profile = - getSpatializerOutputProfile(config, devices); - if (profile == nullptr) { - return false; - } - // The caller can have the audio config criteria ignored by either passing a null ptr or // the AUDIO_CONFIG_INITIALIZER value. // If an audio config is specified, current policy is to only allow spatialization for - // some positional channel masks. + // some positional channel masks and PCM format if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) { if (!audio_is_channel_mask_spatialized(config->channel_mask)) { return false; } + if (!audio_is_linear_pcm(config->format)) { + return false; + } } + + sp profile = + getSpatializerOutputProfile(config, devices); + if (profile == nullptr) { + return false; + } + return true; } From 2c1cd8206db904962731c1da347d9ebefc39c8ce Mon Sep 17 00:00:00 2001 From: Sungtak Lee Date: Tue, 1 Aug 2023 22:32:11 +0000 Subject: [PATCH 086/148] C2BqPool: Invalidate when the client died Invalidate C2BqPool when the client process is dead, and return a proper error when fetchGraphicBlock() is called after the death of the client process. Bug: 291204722 (cherry picked from https://android-review.googlesource.com/q/commit:03cfa6252d238ea7d829cf5842e3921c04fc5173) Merged-In: I54d2b7193b4ce059769258926958927797632137 Change-Id: I54d2b7193b4ce059769258926958927797632137 --- media/codec2/hal/hidl/1.0/utils/Component.cpp | 35 ++++++++++++++++--- .../utils/include/codec2/hidl/1.0/Component.h | 3 ++ media/codec2/hal/hidl/1.1/utils/Component.cpp | 35 ++++++++++++++++--- .../utils/include/codec2/hidl/1.1/Component.h | 3 ++ media/codec2/hal/hidl/1.2/utils/Component.cpp | 35 ++++++++++++++++--- .../utils/include/codec2/hidl/1.2/Component.h | 4 ++- media/codec2/vndk/include/C2BqBufferPriv.h | 7 ++++ media/codec2/vndk/platform/C2BqBuffer.cpp | 15 ++++++++ 8 files changed, 121 insertions(+), 16 deletions(-) diff --git a/media/codec2/hal/hidl/1.0/utils/Component.cpp b/media/codec2/hal/hidl/1.0/utils/Component.cpp index df30dbabe5..0aeed08638 100644 --- a/media/codec2/hal/hidl/1.0/utils/Component.cpp +++ b/media/codec2/hal/hidl/1.0/utils/Component.cpp @@ -222,6 +222,21 @@ c2_status_t Component::status() const { return mInit; } +void Component::onDeathReceived() { + { + std::lock_guard lock(mBlockPoolsMutex); + mClientDied = true; + for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) { + if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) { + std::shared_ptr bqPool = + std::static_pointer_cast(it->second); + bqPool->invalidate(); + } + } + } + release(); +} + // Methods from ::android::hardware::media::c2::V1_0::IComponent Return Component::queue(const WorkBundle& workBundle) { std::list> c2works; @@ -409,9 +424,19 @@ Return Component::createBlockPool( blockPool = nullptr; } if (blockPool) { - mBlockPoolsMutex.lock(); - mBlockPools.emplace(blockPool->getLocalId(), blockPool); - mBlockPoolsMutex.unlock(); + bool emplaced = false; + { + mBlockPoolsMutex.lock(); + if (!mClientDied) { + mBlockPools.emplace(blockPool->getLocalId(), blockPool); + emplaced = true; + } + mBlockPoolsMutex.unlock(); + } + if (!emplaced) { + blockPool.reset(); + status = C2_BAD_STATE; + } } else if (status == C2_OK) { status = C2_CORRUPTED; } @@ -494,8 +519,8 @@ void Component::initListener(const sp& self) { ) override { auto strongComponent = mComponent.promote(); if (strongComponent) { - LOG(INFO) << "Client died ! release the component !!"; - strongComponent->release(); + LOG(INFO) << "Client died ! notify and release the component !!"; + strongComponent->onDeathReceived(); } else { LOG(ERROR) << "Client died ! no component to release !!"; } diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h index e343655fff..3f55618d15 100644 --- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h +++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h @@ -66,6 +66,8 @@ struct Component : public IComponent, const sp<::android::hardware::media::bufferpool::V2_0:: IClientManager>& clientPoolManager); c2_status_t status() const; + // Receives a death notification of the client. + void onDeathReceived(); typedef ::android::hardware::graphics::bufferqueue::V1_0:: IGraphicBufferProducer HGraphicBufferProducer1; @@ -135,6 +137,7 @@ struct Component : public IComponent, using HwDeathRecipient = ::android::hardware::hidl_death_recipient; sp mDeathRecipient; + bool mClientDied{false}; }; } // namespace utils diff --git a/media/codec2/hal/hidl/1.1/utils/Component.cpp b/media/codec2/hal/hidl/1.1/utils/Component.cpp index 2dd922f5ec..d0f4f19662 100644 --- a/media/codec2/hal/hidl/1.1/utils/Component.cpp +++ b/media/codec2/hal/hidl/1.1/utils/Component.cpp @@ -222,6 +222,21 @@ c2_status_t Component::status() const { return mInit; } +void Component::onDeathReceived() { + { + std::lock_guard lock(mBlockPoolsMutex); + mClientDied = true; + for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) { + if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) { + std::shared_ptr bqPool = + std::static_pointer_cast(it->second); + bqPool->invalidate(); + } + } + } + release(); +} + // Methods from ::android::hardware::media::c2::V1_1::IComponent Return Component::queue(const WorkBundle& workBundle) { std::list> c2works; @@ -409,9 +424,19 @@ Return Component::createBlockPool( blockPool = nullptr; } if (blockPool) { - mBlockPoolsMutex.lock(); - mBlockPools.emplace(blockPool->getLocalId(), blockPool); - mBlockPoolsMutex.unlock(); + bool emplaced = false; + { + mBlockPoolsMutex.lock(); + if (!mClientDied) { + mBlockPools.emplace(blockPool->getLocalId(), blockPool); + emplaced = true; + } + mBlockPoolsMutex.unlock(); + } + if (!emplaced) { + blockPool.reset(); + status = C2_BAD_STATE; + } } else if (status == C2_OK) { status = C2_CORRUPTED; } @@ -501,8 +526,8 @@ void Component::initListener(const sp& self) { ) override { auto strongComponent = component.promote(); if (strongComponent) { - LOG(INFO) << "Client died ! release the component !!"; - strongComponent->release(); + LOG(INFO) << "Client died ! notify and release the component !!"; + strongComponent->onDeathReceived(); } else { LOG(ERROR) << "Client died ! no component to release !!"; } diff --git a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h index 1c8c20c5b6..f16de24be5 100644 --- a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h +++ b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/Component.h @@ -69,6 +69,8 @@ struct Component : public IComponent, const sp<::android::hardware::media::bufferpool::V2_0:: IClientManager>& clientPoolManager); c2_status_t status() const; + // Receives a death notification of the client. + void onDeathReceived(); typedef ::android::hardware::graphics::bufferqueue::V1_0:: IGraphicBufferProducer HGraphicBufferProducer1; @@ -140,6 +142,7 @@ struct Component : public IComponent, using HwDeathRecipient = ::android::hardware::hidl_death_recipient; sp mDeathRecipient; + bool mClientDied{false}; }; } // namespace utils diff --git a/media/codec2/hal/hidl/1.2/utils/Component.cpp b/media/codec2/hal/hidl/1.2/utils/Component.cpp index 7994d32f79..036c900eae 100644 --- a/media/codec2/hal/hidl/1.2/utils/Component.cpp +++ b/media/codec2/hal/hidl/1.2/utils/Component.cpp @@ -222,6 +222,21 @@ c2_status_t Component::status() const { return mInit; } +void Component::onDeathReceived() { + { + std::lock_guard lock(mBlockPoolsMutex); + mClientDied = true; + for (auto it = mBlockPools.begin(); it != mBlockPools.end(); ++it) { + if (it->second->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) { + std::shared_ptr bqPool = + std::static_pointer_cast(it->second); + bqPool->invalidate(); + } + } + } + release(); +} + // Methods from ::android::hardware::media::c2::V1_1::IComponent Return Component::queue(const WorkBundle& workBundle) { std::list> c2works; @@ -409,9 +424,19 @@ Return Component::createBlockPool( blockPool = nullptr; } if (blockPool) { - mBlockPoolsMutex.lock(); - mBlockPools.emplace(blockPool->getLocalId(), blockPool); - mBlockPoolsMutex.unlock(); + bool emplaced = false; + { + mBlockPoolsMutex.lock(); + if (!mClientDied) { + mBlockPools.emplace(blockPool->getLocalId(), blockPool); + emplaced = true; + } + mBlockPoolsMutex.unlock(); + } + if (!emplaced) { + blockPool.reset(); + status = C2_BAD_STATE; + } } else if (status == C2_OK) { status = C2_CORRUPTED; } @@ -532,8 +557,8 @@ void Component::initListener(const sp& self) { ) override { auto strongComponent = component.promote(); if (strongComponent) { - LOG(INFO) << "Client died ! release the component !!"; - strongComponent->release(); + LOG(INFO) << "Client died ! notify and release the component !!"; + strongComponent->onDeathReceived(); } else { LOG(ERROR) << "Client died ! no component to release !!"; } diff --git a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/Component.h b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/Component.h index d0972eeedf..6a73392dde 100644 --- a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/Component.h +++ b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/Component.h @@ -69,6 +69,8 @@ struct Component : public IComponent, const sp<::android::hardware::media::bufferpool::V2_0:: IClientManager>& clientPoolManager); c2_status_t status() const; + // Receives a death notification of the client. + void onDeathReceived(); typedef ::android::hardware::graphics::bufferqueue::V1_0:: IGraphicBufferProducer HGraphicBufferProducer1; @@ -145,7 +147,7 @@ struct Component : public IComponent, using HwDeathRecipient = ::android::hardware::hidl_death_recipient; sp mDeathRecipient; - + bool mClientDied{false}; }; } // namespace utils diff --git a/media/codec2/vndk/include/C2BqBufferPriv.h b/media/codec2/vndk/include/C2BqBufferPriv.h index 29aad5ece4..320b192543 100644 --- a/media/codec2/vndk/include/C2BqBufferPriv.h +++ b/media/codec2/vndk/include/C2BqBufferPriv.h @@ -103,6 +103,13 @@ class C2BufferQueueBlockPool : public C2BlockPool { virtual void getConsumerUsage(uint64_t *consumerUsage); + /** + * Invalidate the class. + * + * After the call, fetchGraphicBlock() will return C2_BAD_STATE. + */ + virtual void invalidate(); + private: const std::shared_ptr mAllocator; const local_id_t mLocalId; diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp index f2cd5852f2..5fb0c8f415 100644 --- a/media/codec2/vndk/platform/C2BqBuffer.cpp +++ b/media/codec2/vndk/platform/C2BqBuffer.cpp @@ -601,6 +601,9 @@ class C2BufferQueueBlockPool::Impl static int kMaxIgbpRetryDelayUs = 10000; std::unique_lock lock(mMutex); + if (mInvalidated) { + return C2_BAD_STATE; + } if (mLastDqLogTs == 0) { mLastDqLogTs = getTimestampNow(); } else { @@ -746,6 +749,11 @@ class C2BufferQueueBlockPool::Impl *consumeUsage = mConsumerUsage; } + void invalidate() { + std::scoped_lock lock(mMutex); + mInvalidated = true; + } + private: friend struct C2BufferQueueBlockPoolData; @@ -783,6 +791,7 @@ class C2BufferQueueBlockPool::Impl // if the token has been expired, the buffers will not call IGBP::cancelBuffer() // when they are no longer used. std::shared_ptr mIgbpValidityToken; + bool mInvalidated{false}; }; C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData( @@ -1103,3 +1112,9 @@ void C2BufferQueueBlockPool::getConsumerUsage(uint64_t *consumeUsage) { } } +void C2BufferQueueBlockPool::invalidate() { + if (mImpl) { + mImpl->invalidate(); + } +} + From 4c2392b6793b73edc9103aee7c2c1793710549e1 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Mon, 3 Jul 2023 18:14:07 +0200 Subject: [PATCH 087/148] audio flinger: fix initial mmap stream volume The initial stream volume values received by a MMAP thread while the mmap stream is being open by audio policy manager were ignored because the stream type was not yet initialized (the stream type is received from audio policy manager when getOutputForAttr returns). The fix consists in using the same volume/mute data structure array for MmapPlaybackThread as for PlaybackThread in order to store all stream volume and mute values but only use the one corresponding to the configured mStreamType. Bug: 284836454 Test: repro steps in bug Change-Id: If4654c1d9ea7fd109a8ab2b9b2431db71b966243 Merged-In: If4654c1d9ea7fd109a8ab2b9b2431db71b966243 (cherry picked from commit 1f9b5e66c7f3ffdadfa4a7fac0583f19c5a888c8) --- services/audioflinger/Threads.cpp | 34 ++++++++++++++++++------------- services/audioflinger/Threads.h | 9 ++++++-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 0f4bfa413b..b022a31a5b 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -10614,14 +10614,24 @@ AudioFlinger::MmapPlaybackThread::MmapPlaybackThread( AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady) : MmapThread(audioFlinger, id, hwDev, output->stream, systemReady, true /* isOut */), mStreamType(AUDIO_STREAM_MUSIC), - mStreamVolume(1.0), - mStreamMute(false), mOutput(output) { snprintf(mThreadName, kThreadNameLength, "AudioMmapOut_%X", id); mChannelCount = audio_channel_count_from_out_mask(mChannelMask); mMasterVolume = audioFlinger->masterVolume_l(); mMasterMute = audioFlinger->masterMute_l(); + + for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) { + const audio_stream_type_t stream{static_cast(i)}; + mStreamTypes[stream].volume = 0.0f; + mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream); + } + // Audio patch and call assistant volume are always max + mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f; + mStreamTypes[AUDIO_STREAM_PATCH].mute = false; + mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].volume = 1.0f; + mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false; + if (mAudioHwDev) { if (mAudioHwDev->canSetMasterVolume()) { mMasterVolume = 1.0; @@ -10678,8 +10688,8 @@ void AudioFlinger::MmapPlaybackThread::setMasterMute(bool muted) void AudioFlinger::MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value) { Mutex::Autolock _l(mLock); + mStreamTypes[stream].volume = value; if (stream == mStreamType) { - mStreamVolume = value; broadcast_l(); } } @@ -10687,17 +10697,14 @@ void AudioFlinger::MmapPlaybackThread::setStreamVolume(audio_stream_type_t strea float AudioFlinger::MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const { Mutex::Autolock _l(mLock); - if (stream == mStreamType) { - return mStreamVolume; - } - return 0.0f; + return mStreamTypes[stream].volume; } void AudioFlinger::MmapPlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted) { Mutex::Autolock _l(mLock); + mStreamTypes[stream].mute = muted; if (stream == mStreamType) { - mStreamMute= muted; broadcast_l(); } } @@ -10737,14 +10744,13 @@ NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l { float volume; - if (mMasterMute || mStreamMute) { + if (mMasterMute || streamMuted_l()) { volume = 0; } else { - volume = mMasterVolume * mStreamVolume; + volume = mMasterVolume * streamVolume_l(); } if (volume != mHalVolFloat) { - // Convert volumes from float to 8.24 uint32_t vol = (uint32_t)(volume * (1 << 24)); @@ -10778,8 +10784,8 @@ NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l track->setMetadataHasChanged(); track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(), /*muteState=*/{mMasterMute, - mStreamVolume == 0.f, - mStreamMute, + streamVolume_l() == 0.f, + streamMuted_l(), // TODO(b/241533526): adjust logic to include mute from AppOps false /*muteFromPlaybackRestricted*/, false /*muteFromClientVolume*/, @@ -10892,7 +10898,7 @@ void AudioFlinger::MmapPlaybackThread::dumpInternals_l(int fd, const Vector& args) override; + float streamVolume_l() const { + return mStreamTypes[mStreamType].volume; + } + bool streamMuted_l() const { + return mStreamTypes[mStreamType].mute; + } + stream_type_t mStreamTypes[AUDIO_STREAM_CNT]; audio_stream_type_t mStreamType; float mMasterVolume; - float mStreamVolume; bool mMasterMute; - bool mStreamMute; AudioStreamOut* mOutput; mediautils::atomic_sp mMelProcessor; From 197faf8fb253686f66a2c684807ec525aad0620b Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Thu, 27 Jul 2023 18:27:59 -0700 Subject: [PATCH 088/148] CSD: Add csd start/stop of BT categorized devices BT devices should only compute CSD once they are categorized as headphones/headsets. The AudioService will send as the cached list of BT devices together with their categorization which will allow an initial triage of devices that can calculate the dosage values. There is also a possibility to dynamically change/add new categorizations which will start/stop the CSD computation. Test: atest sounddosemanager_tests Bug: 287011781 Merged-In: I161533a38cb718c28a8c5a8eaf962e0e5055b5a1 Change-Id: I161533a38cb718c28a8c5a8eaf962e0e5055b5a1 --- .../aidl/android/media/ISoundDose.aidl | 24 +++ services/audioflinger/MelReporter.cpp | 150 +++++++++++------- services/audioflinger/MelReporter.h | 20 ++- .../sounddose/SoundDoseManager.cpp | 120 +++++++++++++- .../audioflinger/sounddose/SoundDoseManager.h | 49 +++++- .../tests/sounddosemanager_tests.cpp | 59 ++++++- 6 files changed, 350 insertions(+), 72 deletions(-) diff --git a/media/libaudioclient/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl index 6cb22ef9e1..d80b6bf85e 100644 --- a/media/libaudioclient/aidl/android/media/ISoundDose.aidl +++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl @@ -55,6 +55,30 @@ interface ISoundDose { */ oneway void setCsdEnabled(boolean enabled); + /** + * Structure containing a device identifier by address and type together with + * the categorization whether it is a headphone or not. + */ + @JavaDerive(toString = true) + parcelable AudioDeviceCategory { + @utf8InCpp String address; + int internalAudioType; + boolean csdCompatible; + } + + /** + * Resets the list of stored device categories for the native layer. Should + * only be called once at boot time after parsing the existing AudioDeviceCategories. + */ + oneway void initCachedAudioDeviceCategories(in AudioDeviceCategory[] audioDevices); + + /** + * Sets whether a device for a given address and type is a headphone or not. + * This is used to determine whether we compute the CSD on the given device + * since we can not rely completely on the device annotations. + */ + oneway void setAudioDeviceCategory(in AudioDeviceCategory audioDevice); + /* -------------------------- Test API methods -------------------------- /** Get the currently used RS2 upper bound. */ float getOutputRs2UpperBound(); diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp index 39f772b9ec..3af882813c 100644 --- a/services/audioflinger/MelReporter.cpp +++ b/services/audioflinger/MelReporter.cpp @@ -78,30 +78,8 @@ void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() { void AudioFlinger::MelReporter::onFirstRef() { mAudioFlinger.mPatchCommandThread->addListener(this); -} -bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) { - if (!mSoundDoseManager->isCsdEnabled()) { - ALOGV("%s csd is disabled", __func__); - return false; - } - if (mSoundDoseManager->forceComputeCsdOnAllDevices()) { - return true; - } - - switch (device) { - case AUDIO_DEVICE_OUT_WIRED_HEADSET: - case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: - // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets - // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: - case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: - case AUDIO_DEVICE_OUT_USB_HEADSET: - case AUDIO_DEVICE_OUT_BLE_HEADSET: - case AUDIO_DEVICE_OUT_BLE_BROADCAST: - return true; - default: - return false; - } + mSoundDoseManager = sp::make(sp::fromExisting(this)); } void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle, @@ -127,16 +105,17 @@ void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHan } auto activeMelPatchIt = mActiveMelPatches.find(activeMelPatchId.value()); - if (activeMelPatchIt != mActiveMelPatches.end() - && shouldActivateCsd != activeMelPatchIt->second.csdActive) { - if (activeMelPatchIt->second.csdActive) { - ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle); - stopMelComputationForPatch_l(activeMelPatchIt->second); - } else { - ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle); - startMelComputationForActivePatch_l(activeMelPatchIt->second); + if (activeMelPatchIt != mActiveMelPatches.end()) { + if (shouldActivateCsd != activeMelPatchIt->second.csdActive) { + if (activeMelPatchIt->second.csdActive) { + ALOGV("%s should not compute CSD for stream handle %d", __func__, streamHandle); + stopMelComputationForPatch_l(activeMelPatchIt->second); + } else { + ALOGV("%s should compute CSD for stream handle %d", __func__, streamHandle); + startMelComputationForActivePatch_l(activeMelPatchIt->second); + } + activeMelPatchIt->second.csdActive = shouldActivateCsd; } - activeMelPatchIt->second.csdActive = shouldActivateCsd; } } @@ -159,23 +138,28 @@ void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle, audio_io_handle_t streamHandle = patch.mAudioPatch.sources[0].ext.mix.handle; ActiveMelPatch newPatch; newPatch.streamHandle = streamHandle; + newPatch.csdActive = false; for (size_t i = 0; i < patch.mAudioPatch.num_sinks; ++i) { - if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE - && shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) { + if (patch.mAudioPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE && + mSoundDoseManager->shouldComputeCsdForDeviceType( + patch.mAudioPatch.sinks[i].ext.device.type)) { audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id; - newPatch.deviceHandles.push_back(deviceId); + bool shouldComputeCsd = mSoundDoseManager->shouldComputeCsdForDeviceWithAddress( + patch.mAudioPatch.sinks[i].ext.device.type, + patch.mAudioPatch.sinks[i].ext.device.address); + newPatch.deviceStates.push_back({deviceId, shouldComputeCsd}); + newPatch.csdActive |= shouldComputeCsd; AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type, patch.mAudioPatch.sinks[i].ext.device.address}; mSoundDoseManager->mapAddressToDeviceId(adt, deviceId); } } - if (!newPatch.deviceHandles.empty()) { + if (!newPatch.deviceStates.empty() && newPatch.csdActive) { std::lock_guard _afl(mAudioFlinger.mLock); std::lock_guard _l(mLock); ALOGV("%s add patch handle %d to active devices", __func__, handle); startMelComputationForActivePatch_l(newPatch); - newPatch.csdActive = true; mActiveMelPatches[handle] = newPatch; } } @@ -189,18 +173,41 @@ NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l return; } - for (const auto& deviceHandle : patch.deviceHandles) { - ++mActiveDevices[deviceHandle]; - ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__, - patch.streamHandle, deviceHandle, mActiveDevices[deviceHandle]); - - if (outputThread != nullptr && !useHalSoundDoseInterface_l()) { - outputThread->startMelComputation_l(mSoundDoseManager->getOrCreateProcessorForDevice( - deviceHandle, - patch.streamHandle, - outputThread->mSampleRate, - outputThread->mChannelCount, - outputThread->mFormat)); + for (const auto& device : patch.deviceStates) { + if (device.second) { + ++mActiveDevices[device.first]; + ALOGI("%s add stream %d that uses device %d for CSD, nr of streams: %d", __func__, + patch.streamHandle, device.first, mActiveDevices[device.first]); + + if (outputThread != nullptr && !useHalSoundDoseInterface_l()) { + outputThread->startMelComputation_l( + mSoundDoseManager->getOrCreateProcessorForDevice( + device.first, + patch.streamHandle, + outputThread->mSampleRate, + outputThread->mChannelCount, + outputThread->mFormat)); + } + } + } +} + +void AudioFlinger::MelReporter::startMelComputationForDeviceId(audio_port_handle_t deviceId) { + ALOGV("%s(%d)", __func__, deviceId); + std::lock_guard _laf(mAudioFlinger.mLock); + std::lock_guard _l(mLock); + + for (auto& activeMelPatch : mActiveMelPatches) { + bool csdActive = false; + for (auto& device: activeMelPatch.second.deviceStates) { + if (device.first == deviceId && !device.second) { + device.second = true; + } + csdActive |= device.second; + } + if (csdActive && !activeMelPatch.second.csdActive) { + activeMelPatch.second.csdActive = csdActive; + startMelComputationForActivePatch_l(activeMelPatch.second); } } } @@ -228,7 +235,11 @@ void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) std::lock_guard _afl(mAudioFlinger.mLock); std::lock_guard _l(mLock); - stopMelComputationForPatch_l(melPatch); + if (melPatch.csdActive) { + // only need to stop if patch was active + melPatch.csdActive = false; + stopMelComputationForPatch_l(melPatch); + } } sp AudioFlinger::MelReporter::getSoundDoseInterface( @@ -247,30 +258,47 @@ void AudioFlinger::MelReporter::stopInternalMelComputation() { void AudioFlinger::MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch) NO_THREAD_SAFETY_ANALYSIS // access of AudioFlinger::checkOutputThread_l { - if (!patch.csdActive) { - // no need to stop CSD inactive patches - return; - } - auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle); ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle); - for (const auto& deviceId : patch.deviceHandles) { - if (mActiveDevices[deviceId] > 0) { - --mActiveDevices[deviceId]; - if (mActiveDevices[deviceId] == 0) { + for (const auto& device : patch.deviceStates) { + if (mActiveDevices[device.first] > 0) { + --mActiveDevices[device.first]; + if (mActiveDevices[device.first] == 0) { // no stream is using deviceId anymore - ALOGI("%s removing device %d from active CSD devices", __func__, deviceId); - mSoundDoseManager->clearMapDeviceIdEntries(deviceId); + ALOGI("%s removing device %d from active CSD devices", __func__, device.first); + mSoundDoseManager->clearMapDeviceIdEntries(device.first); } } } + mSoundDoseManager->removeStreamProcessor(patch.streamHandle); if (outputThread != nullptr && !useHalSoundDoseInterface_l()) { outputThread->stopMelComputation_l(); } } +void AudioFlinger::MelReporter::stopMelComputationForDeviceId(audio_port_handle_t deviceId) { + ALOGV("%s(%d)", __func__, deviceId); + std::lock_guard _laf(mAudioFlinger.mLock); + std::lock_guard _l(mLock); + + for (auto& activeMelPatch : mActiveMelPatches) { + bool csdActive = false; + for (auto& device: activeMelPatch.second.deviceStates) { + if (device.first == deviceId && device.second) { + device.second = false; + } + csdActive |= device.second; + } + + if (!csdActive && activeMelPatch.second.csdActive) { + activeMelPatch.second.csdActive = csdActive; + stopMelComputationForPatch_l(activeMelPatch.second); + } + } + +} std::optional AudioFlinger::MelReporter::activePatchStreamHandle_l( audio_io_handle_t streamHandle) { diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h index 2bc33f2169..604046e45b 100644 --- a/services/audioflinger/MelReporter.h +++ b/services/audioflinger/MelReporter.h @@ -29,11 +29,11 @@ constexpr static int kMaxTimestampDeltaInSec = 120; * Class for listening to new patches and starting the MEL computation. MelReporter is * concealed within AudioFlinger, their lifetimes are the same. */ -class MelReporter : public PatchCommandThread::PatchCommandListener { +class MelReporter : public PatchCommandThread::PatchCommandListener, + public IMelReporterCallback { public: explicit MelReporter(AudioFlinger& audioFlinger) - : mAudioFlinger(audioFlinger), - mSoundDoseManager(sp::make()) {} + : mAudioFlinger(audioFlinger) {} void onFirstRef() override; @@ -65,6 +65,10 @@ class MelReporter : public PatchCommandThread::PatchCommandListener { std::string dump(); + // IMelReporterCallback methods + void stopMelComputationForDeviceId(audio_port_handle_t deviceId) override; + void startMelComputationForDeviceId(audio_port_handle_t deviceId) override; + // PatchCommandListener methods void onCreateAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch) override; @@ -80,13 +84,15 @@ class MelReporter : public PatchCommandThread::PatchCommandListener { private: struct ActiveMelPatch { audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE}; - std::vector deviceHandles; + /** + * Stores device ids and whether they are compatible for CSD calculation. + * The boolean value can change since BT audio device types are user-configurable + * to headphones/headsets or other device types. + */ + std::vector> deviceStates; bool csdActive; }; - /** Returns true if we should compute MEL for the given device. */ - bool shouldComputeMelForDeviceType(audio_devices_t device); - void stopInternalMelComputation(); /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */ diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp index a114a384cf..a551857716 100644 --- a/services/audioflinger/sounddose/SoundDoseManager.cpp +++ b/services/audioflinger/sounddose/SoundDoseManager.cpp @@ -299,6 +299,25 @@ binder::Status SoundDoseManager::SoundDose::setCsdEnabled(bool enabled) { return binder::Status::ok(); } +binder::Status SoundDoseManager::SoundDose::initCachedAudioDeviceCategories( + const std::vector& btDeviceCategories) { + ALOGV("%s", __func__); + auto soundDoseManager = mSoundDoseManager.promote(); + if (soundDoseManager != nullptr) { + soundDoseManager->initCachedAudioDeviceCategories(btDeviceCategories); + } + return binder::Status::ok(); +} +binder::Status SoundDoseManager::SoundDose::setAudioDeviceCategory( + const media::ISoundDose::AudioDeviceCategory& btAudioDevice) { + ALOGV("%s", __func__); + auto soundDoseManager = mSoundDoseManager.promote(); + if (soundDoseManager != nullptr) { + soundDoseManager->setAudioDeviceCategory(btAudioDevice); + } + return binder::Status::ok(); +} + binder::Status SoundDoseManager::SoundDose::getOutputRs2UpperBound(float* value) { ALOGV("%s", __func__); auto soundDoseManager = mSoundDoseManager.promote(); @@ -356,7 +375,9 @@ void SoundDoseManager::updateAttenuation(float attenuationDB, audio_devices_t de auto melProcessor = mp.second.promote(); if (melProcessor != nullptr) { auto deviceId = melProcessor->getDeviceId(); - if (mActiveDeviceTypes[deviceId] == deviceType) { + const auto deviceTypeIt = mActiveDeviceTypes.find(deviceId); + if (deviceTypeIt != mActiveDeviceTypes.end() && + deviceTypeIt->second == deviceType) { ALOGV("%s: set attenuation for deviceId %d to %f", __func__, deviceId, attenuationDB); melProcessor->setAttenuation(attenuationDB); @@ -388,6 +409,103 @@ bool SoundDoseManager::isCsdEnabled() { return mEnabledCsd; } +void SoundDoseManager::initCachedAudioDeviceCategories( + const std::vector& deviceCategories) { + ALOGV("%s", __func__); + { + const std::lock_guard _l(mLock); + mBluetoothDevicesWithCsd.clear(); + } + for (const auto& btDeviceCategory : deviceCategories) { + setAudioDeviceCategory(btDeviceCategory); + } +} + +void SoundDoseManager::setAudioDeviceCategory( + const media::ISoundDose::AudioDeviceCategory& audioDevice) { + ALOGV("%s: set BT audio device type with address %s to headphone %d", __func__, + audioDevice.address.c_str(), audioDevice.csdCompatible); + + std::vector devicesToStart; + std::vector devicesToStop; + { + const std::lock_guard _l(mLock); + const auto deviceIt = mBluetoothDevicesWithCsd.find( + std::make_pair(audioDevice.address, + static_cast(audioDevice.internalAudioType))); + if (deviceIt != mBluetoothDevicesWithCsd.end()) { + deviceIt->second = audioDevice.csdCompatible; + } else { + mBluetoothDevicesWithCsd.emplace( + std::make_pair(audioDevice.address, + static_cast(audioDevice.internalAudioType)), + audioDevice.csdCompatible); + } + + for (const auto &activeDevice: mActiveDevices) { + if (activeDevice.first.address() == audioDevice.address && + activeDevice.first.mType == + static_cast(audioDevice.internalAudioType)) { + if (audioDevice.csdCompatible) { + devicesToStart.push_back(activeDevice.second); + } else { + devicesToStop.push_back(activeDevice.second); + } + } + } + } + + for (const auto& deviceToStart : devicesToStart) { + mMelReporterCallback->startMelComputationForDeviceId(deviceToStart); + } + for (const auto& deviceToStop : devicesToStop) { + mMelReporterCallback->stopMelComputationForDeviceId(deviceToStop); + } +} + +bool SoundDoseManager::shouldComputeCsdForDeviceType(audio_devices_t device) { + if (!isCsdEnabled()) { + ALOGV("%s csd is disabled", __func__); + return false; + } + if (forceComputeCsdOnAllDevices()) { + return true; + } + + switch (device) { + case AUDIO_DEVICE_OUT_WIRED_HEADSET: + case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: + // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets + // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: + case AUDIO_DEVICE_OUT_USB_HEADSET: + case AUDIO_DEVICE_OUT_BLE_HEADSET: + case AUDIO_DEVICE_OUT_BLE_BROADCAST: + return true; + default: + return false; + } +} + +bool SoundDoseManager::shouldComputeCsdForDeviceWithAddress(const audio_devices_t type, + const std::string& deviceAddress) { + if (!isCsdEnabled()) { + ALOGV("%s csd is disabled", __func__); + return false; + } + if (forceComputeCsdOnAllDevices()) { + return true; + } + + if (!audio_is_ble_out_device(type) && !audio_is_a2dp_device(type)) { + return shouldComputeCsdForDeviceType(type); + } + + const std::lock_guard _l(mLock); + const auto deviceIt = mBluetoothDevicesWithCsd.find(std::make_pair(deviceAddress, type)); + return deviceIt != mBluetoothDevicesWithCsd.end() && deviceIt->second; +} + void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) { // invalidate any HAL sound dose interface used setHalSoundDoseInterface(nullptr); diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h index 6c02afb258..718913d6a1 100644 --- a/services/audioflinger/sounddose/SoundDoseManager.h +++ b/services/audioflinger/sounddose/SoundDoseManager.h @@ -32,6 +32,15 @@ namespace android { using aidl::android::hardware::audio::core::sounddose::ISoundDose; +class IMelReporterCallback : public virtual RefBase { +public: + IMelReporterCallback() {}; + virtual ~IMelReporterCallback() {}; + + virtual void stopMelComputationForDeviceId(audio_port_handle_t deviceId) = 0; + virtual void startMelComputationForDeviceId(audio_port_handle_t deviceId) = 0; +}; + class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { public: /** CSD is computed with a rolling window of 7 days. */ @@ -39,8 +48,9 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { /** Default RS2 upper bound in dBA as defined in IEC 62368-1 3rd edition. */ static constexpr float kDefaultRs2UpperBound = 100.f; - SoundDoseManager() - : mMelAggregator(sp::make(kCsdWindowSeconds)), + explicit SoundDoseManager(const sp& melReporterCallback) + : mMelReporterCallback(melReporterCallback), + mMelAggregator(sp::make(kCsdWindowSeconds)), mRs2UpperBound(kDefaultRs2UpperBound) {}; /** @@ -104,6 +114,21 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { /** Returns true if CSD is enabled. */ bool isCsdEnabled(); + void initCachedAudioDeviceCategories( + const std::vector& deviceCategories); + + void setAudioDeviceCategory( + const media::ISoundDose::AudioDeviceCategory& audioDevice); + + /** + * Returns true if the type can compute CSD. For bluetooth devices we rely on whether we + * categorized the address as headphones/headsets, only in this case we return true. + */ + bool shouldComputeCsdForDeviceWithAddress(const audio_devices_t type, + const std::string& deviceAddress); + /** Returns true for all device types which could support CSD computation. */ + bool shouldComputeCsdForDeviceType(audio_devices_t device); + std::string dump() const; // used for testing only @@ -139,6 +164,13 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { binder::Status getOutputRs2UpperBound(float* value) override; binder::Status setCsdEnabled(bool enabled) override; + binder::Status initCachedAudioDeviceCategories( + const std::vector &btDeviceCategories) + override; + + binder::Status setAudioDeviceCategory( + const media::ISoundDose::AudioDeviceCategory& btAudioDevice) override; + binder::Status getCsd(float* value) override; binder::Status forceUseFrameworkMel(bool useFrameworkMel) override; binder::Status forceComputeCsdOnAllDevices(bool computeCsdOnAllDevices) override; @@ -179,6 +211,8 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { mutable std::mutex mLock; + const sp mMelReporterCallback; + // no need for lock since MelAggregator is thread-safe const sp mMelAggregator; @@ -191,6 +225,17 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { std::map mActiveDevices GUARDED_BY(mLock); std::unordered_map mActiveDeviceTypes GUARDED_BY(mLock); + struct bt_device_type_hash { + std::size_t operator() (const std::pair &deviceType) const { + return std::hash()(deviceType.first) ^ + std::hash()(deviceType.second); + } + }; + // storing the BT cached information as received from the java side + // see SoundDoseManager::setCachedAudioDeviceCategories + std::unordered_map, bool, bt_device_type_hash> + mBluetoothDevicesWithCsd GUARDED_BY(mLock); + float mRs2UpperBound GUARDED_BY(mLock); std::unordered_map mMelAttenuationDB GUARDED_BY(mLock); diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp index 9fab77d567..7d0b3a76ff 100644 --- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp +++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp @@ -39,10 +39,18 @@ class HalSoundDoseMock : public BnSoundDose { (const std::shared_ptr&), (override)); }; +class MelReporterCallback : public IMelReporterCallback { +public: + MOCK_METHOD(void, startMelComputationForDeviceId, (audio_port_handle_t), (override)); + MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override)); +}; + + class SoundDoseManagerTest : public ::testing::Test { protected: void SetUp() override { - mSoundDoseManager = sp::make(); + mMelReporterCallback = sp::make(); + mSoundDoseManager = sp::make(mMelReporterCallback); mHalSoundDose = ndk::SharedRefBase::make(); ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound) @@ -52,6 +60,7 @@ class SoundDoseManagerTest : public ::testing::Test { }); } + sp mMelReporterCallback; sp mSoundDoseManager; std::shared_ptr mHalSoundDose; }; @@ -243,5 +252,53 @@ TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) { EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel()); } +TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStopsNonHeadphone) { + media::ISoundDose::AudioDeviceCategory device1; + device1.address = "dev1"; + device1.csdCompatible = false; + device1.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; + const AudioDeviceTypeAddr dev1Adt{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, device1.address}; + + // this will mark the device as active + mSoundDoseManager->mapAddressToDeviceId(dev1Adt, /*deviceId=*/1); + EXPECT_CALL(*mMelReporterCallback.get(), stopMelComputationForDeviceId).Times(1); + + mSoundDoseManager->setAudioDeviceCategory(device1); +} + +TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStartsHeadphone) { + media::ISoundDose::AudioDeviceCategory device1; + device1.address = "dev1"; + device1.csdCompatible = true; + device1.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; + const AudioDeviceTypeAddr dev1Adt{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, device1.address}; + + // this will mark the device as active + mSoundDoseManager->mapAddressToDeviceId(dev1Adt, /*deviceId=*/1); + EXPECT_CALL(*mMelReporterCallback.get(), startMelComputationForDeviceId).Times(1); + + mSoundDoseManager->setAudioDeviceCategory(device1); +} + +TEST_F(SoundDoseManagerTest, InitCachedAudioDevicesStartsOnlyActiveDevices) { + media::ISoundDose::AudioDeviceCategory device1; + media::ISoundDose::AudioDeviceCategory device2; + device1.address = "dev1"; + device1.csdCompatible = true; + device1.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; + device2.address = "dev2"; + device2.csdCompatible = true; + device2.internalAudioType = AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; + const AudioDeviceTypeAddr dev1Adt{AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, device1.address}; + std::vector btDevices = {device1, device2}; + + // this will mark the device as active + mSoundDoseManager->mapAddressToDeviceId(dev1Adt, /*deviceId=*/1); + EXPECT_CALL(*mMelReporterCallback.get(), startMelComputationForDeviceId).Times(1); + + mSoundDoseManager->initCachedAudioDeviceCategories(btDevices); +} + + } // namespace } // namespace android From e828e5622d72cfb3ce79683b0f52f20cd825900a Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Fri, 4 Aug 2023 14:42:14 -0700 Subject: [PATCH 089/148] Align AIDL HAL config reporting with legacy 1. In libaudiohal, sort the modules in the "canonical" order, as in the reference audio_policy_configuration_7_0.xml file. This simplifies A/B comparisons. 2. When building the APM configuration from the one provided by the AIDL HAL, insert "dynamic profiles" into the mix port if it has an empty set of profiles (same as for device ports). Bug: 286914845 Bug: 290273817 Test: run CF with AIDL HAL, A/B compare APM dumps with HIDL Change-Id: Ifc645d0b1318ceaa6a3935bf470f2d045d518800 (cherry picked from commit 1f8cf3d2c1e44bacc01227fbea75b46dfb75abf2) Merged-In: Ifc645d0b1318ceaa6a3935bf470f2d045d518800 --- .../libaudiohal/impl/DevicesFactoryHalAidl.cpp | 18 ++++++++++++++++++ .../src/AudioPolicyConfig.cpp | 7 ++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp index f00b1a06b7..a8f9f7e66e 100644 --- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp +++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp @@ -14,7 +14,10 @@ * limitations under the License. */ +#include +#include #include +#include #define LOG_TAG "DevicesFactoryHalAidl" //#define LOG_NDEBUG 0 @@ -75,6 +78,21 @@ status_t DevicesFactoryHalAidl::getDeviceNames(std::vector *names) if (strcmp(instance, "default") == 0) instance = "primary"; static_cast(context)->push_back(instance); }); + std::sort(names->begin(), names->end(), [](const std::string& lhs, + const std::string& rhs) { + // This order corresponds to the canonical order of modules as specified in + // the reference 'audio_policy_configuration_7_0.xml' file. + static const std::map kPriorities{ + { "primary", 0 }, { "a2dp", 1 }, { "usb", 2 }, { "r_submix", 3 }, + { "bluetooth", 4 }, { "hearing_aid", 5 }, { "msd", 6 }, { "stub", 7 } + }; + auto lhsIt = kPriorities.find(lhs); + auto rhsIt = kPriorities.find(rhs); + if (lhsIt != kPriorities.end() && rhsIt != kPriorities.end()) { + return lhsIt->second < rhsIt->second; + } + return lhsIt != kPriorities.end(); + }); return OK; } diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp index e214ae9c40..8c7a7de36f 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp @@ -89,7 +89,12 @@ status_t aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule& aidl, if (aidlPort.ext.getTag() == AudioPortExt::mix) { auto mixPort = sp::make("", AUDIO_PORT_ROLE_NONE); RETURN_STATUS_IF_ERROR(mixPort->readFromParcelable(fwPort)); - sortAudioProfiles(mixPort->getAudioProfiles()); + auto& profiles = mixPort->getAudioProfiles(); + if (profiles.empty()) { + profiles.add(AudioProfile::createFullDynamic(gDynamicFormat)); + } else { + sortAudioProfiles(mixPort->getAudioProfiles()); + } mixPorts.add(mixPort); ports.emplace(aidlPort.id, mixPort); } else if (aidlPort.ext.getTag() == AudioPortExt::device) { From 82ed435e2cb0ab45364202917a17d5bd241abace Mon Sep 17 00:00:00 2001 From: malikakash Date: Fri, 21 Jul 2023 22:44:34 +0000 Subject: [PATCH 090/148] Implement Camera Id Remapping in CameraService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0. We reuse the CAMERA_INJECT_EXTERNAL_CAMERA permission to restrict access to the new Camera ID Remapping functionality. 1. Introduce a new binder method remapCameraIds(CameraIdRemapping). 2. The CameraIdRemapping parcelable is just a map of {packageName -> {id0 -> id1}} and is used between CameraManager <-> CameraService. 3. The methods in ICameraService that deal with Camera ID simply call resolveCameraId(id) to find the actual ID to use. Behind the scenes, we also use the UID to lookup the packageName associated with the client to find the associated camera ID. 4. Every time we update the config, we disconnect the clients that are used by the packages that we plan to replace. See the impl in remapCameraIds. 5. For CameraManager listeners for packages which have active ID remapping, we trigger all callbacks (torch, statusUpdates) for both the id0 as well as id1 - meaning, if we get onStatusChanged(id1), and package com.instagram.android has an active remapping of {id0->id1}, we’ll trigger onStatusChanged(id0) as well (to allow the app to receive updates on the camera it thinks it is talking to). 6. Because the CameraDevice in the application layer still only knows about the original (pre-configuration) IDs, the CaptureRequests it sends down also contain that original ID. So, we have to change some logic in CameraDeviceClient to allow it to modify the id while processing the requests. This also means that CameraDeviceClient should know both its remapped ID and the original Id it was created for. 7. To simulate and demonstrate live updates to the id mapping configuration, we add a shell command to invoke remapCameraIds dynamically via `adb shell cmd media.camera remap-camera-id packageName id0 id1`. This will only be allowed via adb root. Security Bug: b/288901406 (For clearance related to the effort and the permission design) Bug: b/286287541 Test: Manual testing Change-Id: I785a70bffad304583cfe557114b003a51cf5ac43 Merged-In: Ie1d726c45032ee8e7b9773640f96465451167dc9 --- camera/Android.bp | 1 + .../android/hardware/CameraIdRemapping.aidl | 50 ++++ .../aidl/android/hardware/ICameraService.aidl | 17 ++ .../camera/libcameraservice/CameraService.cpp | 242 ++++++++++++++++-- .../camera/libcameraservice/CameraService.h | 68 ++++- .../api2/CameraDeviceClient.cpp | 23 +- .../api2/CameraDeviceClient.h | 6 +- 7 files changed, 363 insertions(+), 44 deletions(-) create mode 100644 camera/aidl/android/hardware/CameraIdRemapping.aidl diff --git a/camera/Android.bp b/camera/Android.bp index b3f70f4a2a..a3fd7f9082 100644 --- a/camera/Android.bp +++ b/camera/Android.bp @@ -144,6 +144,7 @@ filegroup { srcs: [ "aidl/android/hardware/CameraExtensionSessionStats.aidl", "aidl/android/hardware/ICameraService.aidl", + "aidl/android/hardware/CameraIdRemapping.aidl", "aidl/android/hardware/ICameraServiceListener.aidl", "aidl/android/hardware/ICameraServiceProxy.aidl", "aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl", diff --git a/camera/aidl/android/hardware/CameraIdRemapping.aidl b/camera/aidl/android/hardware/CameraIdRemapping.aidl new file mode 100644 index 0000000000..ab0a39ce1b --- /dev/null +++ b/camera/aidl/android/hardware/CameraIdRemapping.aidl @@ -0,0 +1,50 @@ +/* + * 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.hardware; + +/** + * Specifies a remapping of Camera Ids. + * + * Example: For a given package, a remapping of camera id0 to id1 specifies + * that any operation to perform on id0 should instead be performed on id1. + * + * @hide + */ +parcelable CameraIdRemapping { + /** + * Specifies remapping of Camera Ids per package. + */ + parcelable PackageIdRemapping { + /** Package Name (e.g. com.android.xyz). */ + String packageName; + /** + * Ordered list of Camera Ids to replace. Only Camera Ids present in this list will be + * affected. + */ + String[] cameraIdToReplace; + /** + * Ordered list of updated Camera Ids, where updatedCameraId[i] corresponds to + * the updated camera id for cameraIdToReplace[i]. + */ + String[] updatedCameraId; + } + + /** + * List of Camera Id remappings to perform. + */ + List packageIdRemapping; +} diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl index f8e16312ea..01b8ff89c1 100644 --- a/camera/aidl/android/hardware/ICameraService.aidl +++ b/camera/aidl/android/hardware/ICameraService.aidl @@ -29,6 +29,7 @@ import android.hardware.camera2.utils.CameraIdAndSessionConfiguration; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.ICameraServiceListener; import android.hardware.CameraInfo; +import android.hardware.CameraIdRemapping; import android.hardware.CameraStatus; import android.hardware.CameraExtensionSessionStats; @@ -130,6 +131,22 @@ interface ICameraService in CameraIdAndSessionConfiguration[] sessions, int targetSdkVersion); + /** + * Remap Camera Ids in the CameraService. + * + * Once this is in effect, all binder calls in the ICameraService that + * use logicalCameraId should consult remapping state to arrive at the + * correct cameraId to perform the operation on. + * + * Note: Before the new cameraIdRemapping state is applied, the previous + * state is cleared. + * + * @param cameraIdRemapping the camera ids to remap. Sending an unpopulated + * cameraIdRemapping object will result in clearing of any previous + * cameraIdRemapping state in the camera service. + */ + void remapCameraIds(in CameraIdRemapping cameraIdRemapping); + /** * Remove listener for changes to camera device and flashlight state. */ diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index d1351cf64f..7551bd793b 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -316,14 +316,24 @@ void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeS for (auto& i : mListenerList) { if (shouldSkipStatusUpdates(systemCameraKind, i->isVendorListener(), i->getListenerPid(), i->getListenerUid())) { - ALOGV("Skipping torch callback for system-only camera device %s", - cameraId.c_str()); + ALOGV("%s: Skipping torch callback for system-only camera device %s", + __FUNCTION__, cameraId.c_str()); continue; } auto ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), String16{cameraId}); i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d", __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode()); + // Also trigger the torch callbacks for cameras that were remapped to the current cameraId + // for the specific package that this listener belongs to. + std::vector remappedCameraIds = + findOriginalIdsForRemappedCameraId(cameraId, i->getListenerUid()); + for (auto& remappedCameraId : remappedCameraIds) { + ret = i->getListener()->onTorchStatusChanged(mapToInterface(status), + String16(remappedCameraId)); + i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d", + __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode()); + } } } @@ -745,6 +755,144 @@ Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) { return Status::ok(); } +Status CameraService::remapCameraIds(const hardware::CameraIdRemapping& + cameraIdRemapping) { + if (!checkCallingPermission(sCameraInjectExternalCameraPermission)) { + const int pid = CameraThreadState::getCallingPid(); + const int uid = CameraThreadState::getCallingUid(); + ALOGE("%s: Permission Denial: can't configure camera ID mapping pid=%d, uid=%d", + __FUNCTION__, pid, uid); + return STATUS_ERROR(ERROR_PERMISSION_DENIED, + "Permission Denial: no permission to configure camera id mapping"); + } + TCameraIdRemapping cameraIdRemappingMap{}; + binder::Status parseStatus = parseCameraIdRemapping(cameraIdRemapping, cameraIdRemappingMap); + if (!parseStatus.isOk()) { + return parseStatus; + } + remapCameraIds(cameraIdRemappingMap); + return Status::ok(); +} + +Status CameraService::parseCameraIdRemapping( + const hardware::CameraIdRemapping& cameraIdRemapping, + TCameraIdRemapping cameraIdRemappingMap) { + String16 packageName; + String8 cameraIdToReplace, updatedCameraId; + for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemapping) { + packageName = packageIdRemapping.packageName; + if (packageName == String16("")) { + return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, + "CameraIdRemapping: Package name cannot be empty"); + } + if (packageIdRemapping.cameraIdToReplace.size() + != packageIdRemapping.updatedCameraId.size()) { + return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, + "CameraIdRemapping: Mismatch in CameraId Remapping lists sizes for package %s", + String8(packageName).c_str()); + } + for(size_t i = 0; i < packageIdRemapping.cameraIdToReplace.size(); i++) { + cameraIdToReplace = String8(packageIdRemapping.cameraIdToReplace[i]); + updatedCameraId = String8(packageIdRemapping.updatedCameraId[i]); + cameraIdRemappingMap[packageName][cameraIdToReplace] = updatedCameraId; + } + } + return Status::ok(); +} + +void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) { + // Acquire mServiceLock and prevent other clients from connecting + std::unique_ptr serviceLockWrapper = + AutoConditionLock::waitAndAcquire(mServiceLockWrapper); + + Mutex::Autolock lock(mCameraIdRemappingLock); + // This will disconnect all existing clients for camera Ids that are being + // remapped in cameraIdRemapping, but only if they were being used by an + // affected packageName. + std::vector> clientsToDisconnect; + std::vector cameraIdsToUpdate; + for (const auto& [packageName, injectionMap] : cameraIdRemapping) { + for (auto& [id0, id1] : injectionMap) { + ALOGI("%s: UPDATE:= %s: %s: %s", __FUNCTION__, String8(packageName).c_str(), + id0.c_str(), id1.c_str()); + auto clientDescriptor = mActiveClientManager.get(id0); + if (clientDescriptor != nullptr) { + sp clientSp = clientDescriptor->getValue(); + if (clientSp->getPackageName() == packageName) { + // This camera ID is being used by the affected packageName. + clientsToDisconnect.push_back(clientSp); + cameraIdsToUpdate.push_back(id0); + } + } + } + } + + // Update mCameraIdRemapping. + mCameraIdRemapping.clear(); + mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end()); + + // Do not hold mServiceLock while disconnecting clients, but retain the condition + // blocking other clients from connecting in mServiceLockWrapper if held. + mServiceLock.unlock(); + + // Disconnect clients. + for (auto& clientSp : clientsToDisconnect) { + // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect + // automatically. + clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE, + CaptureResultExtras{}); + // This also triggers the status updates + clientSp->disconnect(); + } + + mServiceLock.lock(); +} + +std::vector CameraService::findOriginalIdsForRemappedCameraId( + const String8& inputCameraId, int clientUid) { + String16 packageName = getPackageNameFromUid(clientUid); + std::vector cameraIds; + Mutex::Autolock lock(mCameraIdRemappingLock); + if (auto packageMapIter = mCameraIdRemapping.find(packageName); + packageMapIter != mCameraIdRemapping.end()) { + for (auto& [id0, id1]: packageMapIter->second) { + if (id1 == inputCameraId) { + cameraIds.push_back(id0); + } + } + } + return cameraIds; +} + +String8 CameraService::resolveCameraId(const String8& inputCameraId) { + return resolveCameraId(inputCameraId, String16("")); +} + +String8 CameraService::resolveCameraId( + const String8& inputCameraId, + const String16& packageName) { + String16 packageNameVal = packageName; + if (packageName == String16("")) { + int clientUid = CameraThreadState::getCallingUid(); + packageNameVal = getPackageNameFromUid(clientUid); + } + Mutex::Autolock lock(mCameraIdRemappingLock); + if (auto packageMapIter = mCameraIdRemapping.find(packageNameVal); + packageMapIter != mCameraIdRemapping.end()) { + ALOGI("%s: resolveCameraId: packageName found %s", + __FUNCTION__, String8(packageNameVal).c_str()); + auto packageMap = packageMapIter->second; + if (auto replacementIdIter = packageMap.find(inputCameraId); + replacementIdIter != packageMap.end()) { + ALOGI("%s: resolveCameraId: inputId found %s, replacing with %s", + __FUNCTION__, inputCameraId.c_str(), + replacementIdIter->second.c_str()); + return replacementIdIter->second; + } + } + return inputCameraId; +} + Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait, CameraInfo* cameraInfo) { ATRACE_CALL(); @@ -815,9 +963,10 @@ String8 CameraService::cameraIdIntToStr(int cameraIdInt) { return String8(cameraIdIntToStrLocked(cameraIdInt).c_str()); } -Status CameraService::getCameraCharacteristics(const String16& cameraId, +Status CameraService::getCameraCharacteristics(const String16& unresolvedCameraId, int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) { ATRACE_CALL(); + String8 cameraId = resolveCameraId(String8(unresolvedCameraId)); if (!cameraInfo) { ALOGE("%s: cameraInfo is NULL", __FUNCTION__); return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL"); @@ -837,8 +986,7 @@ Status CameraService::getCameraCharacteristics(const String16& cameraId, Status ret{}; - - std::string cameraIdStr = String8(cameraId).string(); + std::string cameraIdStr = cameraId.string(); bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(mPerfClassPrimaryCameraIds, cameraIdStr, targetSdkVersion); @@ -1028,7 +1176,7 @@ Status CameraService::makeClient(const sp& cameraService, int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid, std::pair deviceVersionAndTransport, apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait, - bool forceSlowJpegMode, /*out*/sp* client) { + bool forceSlowJpegMode, const String8& originalCameraId, /*out*/sp* client) { // For HIDL devices if (deviceVersionAndTransport.second == IPCTransport::HIDL) { // Create CameraClient based on device version reported by the HAL. @@ -1071,7 +1219,7 @@ Status CameraService::makeClient(const sp& cameraService, *client = new CameraDeviceClient(cameraService, tmp, cameraService->mCameraServiceProxyWrapper, packageName, systemNativeClient, featureId, cameraId, facing, sensorOrientation, clientPid, clientUid, servicePid, - overrideForPerfClass, overrideToPortrait); + overrideForPerfClass, overrideToPortrait, originalCameraId); ALOGI("%s: Camera2 API, override to portrait %d", __FUNCTION__, overrideToPortrait); } return Status::ok(); @@ -1163,7 +1311,7 @@ Status CameraService::initializeShimMetadata(int cameraId) { internalPackageName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID, API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0, /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true, - /*forceSlowJpegMode*/false, /*out*/ tmp) + /*forceSlowJpegMode*/false, id, /*out*/ tmp) ).isOk()) { ALOGE("%s: Error initializing shim metadata: %s", __FUNCTION__, ret.toString8().string()); } @@ -1700,7 +1848,7 @@ Status CameraService::connect( ret = connectHelper(cameraClient, id, api1CameraId, clientPackageName,/*systemNativeClient*/ false, {}, clientUid, clientPid, API_1, /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion, - overrideToPortrait, forceSlowJpegMode, /*out*/client); + overrideToPortrait, forceSlowJpegMode, id, /*out*/client); if(!ret.isOk()) { logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName), @@ -1780,7 +1928,7 @@ bool CameraService::shouldRejectSystemCameraConnection(const String8& cameraId) Status CameraService::connectDevice( const sp& cameraCb, - const String16& cameraId, + const String16& unresolvedCameraId, const String16& clientPackageName, const std::optional& clientFeatureId, int clientUid, int oomScoreOffset, int targetSdkVersion, @@ -1790,7 +1938,7 @@ Status CameraService::connectDevice( ATRACE_CALL(); Status ret = Status::ok(); - String8 id = String8(cameraId); + String8 id = resolveCameraId(String8(unresolvedCameraId), clientPackageName); sp client = nullptr; String16 clientPackageNameAdj = clientPackageName; int callingPid = CameraThreadState::getCallingPid(); @@ -1840,7 +1988,7 @@ Status CameraService::connectDevice( /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient,clientFeatureId, clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false, - /*out*/client); + String8(unresolvedCameraId), /*out*/client); if(!ret.isOk()) { logRejected(id, callingPid, String8(clientPackageNameAdj), ret.toString8()); @@ -1909,7 +2057,7 @@ Status CameraService::connectHelper(const sp& cameraCb, const String8& int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient, const std::optional& clientFeatureId, int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion, - bool overrideToPortrait, bool forceSlowJpegMode, + bool overrideToPortrait, bool forceSlowJpegMode, const String8& originalCameraId, /*out*/sp& device) { binder::Status ret = binder::Status::ok(); @@ -2026,7 +2174,7 @@ Status CameraService::connectHelper(const sp& cameraCb, const String8& clientFeatureId, cameraId, api1CameraId, facing, orientation, clientPid, clientUid, getpid(), deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass, - overrideToPortrait, forceSlowJpegMode, + overrideToPortrait, forceSlowJpegMode, originalCameraId, /*out*/&tmp)).isOk()) { return ret; } @@ -2281,7 +2429,8 @@ status_t CameraService::addOfflineClient(String8 cameraId, sp offli return OK; } -Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int32_t torchStrength, +Status CameraService::turnOnTorchWithStrengthLevel(const String16& unresolvedCameraId, + int32_t torchStrength, const sp& clientBinder) { Mutex::Autolock lock(mServiceLock); @@ -2292,7 +2441,7 @@ Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int "Torch client binder in null."); } - String8 id = String8(cameraId.string()); + String8 id = resolveCameraId(String8(unresolvedCameraId)); int uid = CameraThreadState::getCallingUid(); if (shouldRejectSystemCameraConnection(id)) { @@ -2352,7 +2501,7 @@ Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int { Mutex::Autolock al(mTorchUidMapMutex); - updateTorchUidMapLocked(cameraId, uid); + updateTorchUidMapLocked(String16(id), uid); } // Check if the current torch strength level is same as the new one. bool shouldSkipTorchStrengthUpdates = mCameraProviderManager->shouldSkipTorchStrengthUpdate( @@ -2411,7 +2560,8 @@ Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int return Status::ok(); } -Status CameraService::setTorchMode(const String16& cameraId, bool enabled, +Status CameraService::setTorchMode(const String16& unresolvedCameraId, + bool enabled, const sp& clientBinder) { Mutex::Autolock lock(mServiceLock); @@ -2422,7 +2572,7 @@ Status CameraService::setTorchMode(const String16& cameraId, bool enabled, "Torch client Binder is null"); } - String8 id = String8(cameraId.string()); + String8 id = resolveCameraId(String8(unresolvedCameraId)); int uid = CameraThreadState::getCallingUid(); if (shouldRejectSystemCameraConnection(id)) { @@ -2482,7 +2632,7 @@ Status CameraService::setTorchMode(const String16& cameraId, bool enabled, // Update UID map - this is used in the torch status changed callbacks, so must be done // before setTorchMode Mutex::Autolock al(mTorchUidMapMutex); - updateTorchUidMapLocked(cameraId, uid); + updateTorchUidMapLocked(String16(id), uid); } status_t err = mFlashlight->setTorchMode(id, enabled); @@ -2947,11 +3097,20 @@ Status CameraService::getLegacyParameters(int cameraId, /*out*/String16* paramet return ret; } -Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion, +Status CameraService::supportsCameraApi(const String16& unresolvedCameraId, int apiVersion, /*out*/ bool *isSupported) { ATRACE_CALL(); - const String8 id = String8(cameraId); + String8 resolvedId; + if (apiVersion == API_VERSION_2) { + resolvedId = resolveCameraId(String8(unresolvedCameraId)); + } else { // if (apiVersion == API_VERSION_1) + // We don't support remapping for API 1. + // TODO(b/286287541): Also support remapping for API 1. + resolvedId = String8(unresolvedCameraId); + } + + const String8 id = resolvedId; ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string()); @@ -3011,11 +3170,11 @@ Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion return Status::ok(); } -Status CameraService::isHiddenPhysicalCamera(const String16& cameraId, +Status CameraService::isHiddenPhysicalCamera(const String16& unresolvedCameraId, /*out*/ bool *isSupported) { ATRACE_CALL(); - const String8 id = String8(cameraId); + const String8 id = resolveCameraId(String8(unresolvedCameraId)); ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string()); *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string()); @@ -4958,7 +5117,6 @@ void CameraService::updateStatus(StatusInternal status, const String8& cameraId, state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind, &logicalCameraIds] (const String8& cameraId, StatusInternal status) { - if (status != StatusInternal::ENUMERATING) { // Update torch status if it has a flash unit. Mutex::Autolock al(mTorchStatusMutex); @@ -4991,9 +5149,21 @@ void CameraService::updateStatus(StatusInternal status, const String8& cameraId, auto ret = listener->getListener()->onStatusChanged(mapToInterface(status), String16(cameraId)); listener->handleBinderStatus(ret, - "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", + "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(), ret.exceptionCode()); + // Also trigger the callbacks for cameras that were remapped to the current + // cameraId for the specific package that this listener belongs to. + std::vector remappedCameraIds = + findOriginalIdsForRemappedCameraId(cameraId, listener->getListenerUid()); + for (auto& remappedCameraId : remappedCameraIds) { + ret = listener->getListener()->onStatusChanged( + mapToInterface(status), String16(remappedCameraId)); + listener->handleBinderStatus(ret, + "%s: Failed to trigger onStatusChanged callback for %d:%d: %d", + __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(), + ret.exceptionCode()); + } } }); } @@ -5204,6 +5374,8 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector= 2 && args[0] == String16("set-watchdog")) { return handleSetCameraServiceWatchdog(args); + } else if (args.size() >= 4 && args[0] == String16("remap-camera-id")) { + return handleCameraIdRemapping(args, err); } else if (args.size() == 1 && args[0] == String16("help")) { printHelp(out); return OK; @@ -5212,6 +5384,23 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector& args, int err) { + uid_t uid = IPCThreadState::self()->getCallingUid(); + if (uid != AID_ROOT) { + dprintf(err, "Must be adb root\n"); + return PERMISSION_DENIED; + } + if (args.size() != 4) { + dprintf(err, "Expected format: remap-camera-id \n"); + return BAD_VALUE; + } + String16 packageName = args[1]; + String8 cameraIdToReplace = String8(args[2]); + String8 cameraIdNew = String8(args[3]); + remapCameraIds({{packageName, {{cameraIdToReplace, cameraIdNew}}}}); + return OK; +} + status_t CameraService::handleSetUidState(const Vector& args, int err) { String16 packageName = args[1]; @@ -5839,6 +6028,7 @@ status_t CameraService::printHelp(int out) { " clear-stream-use-case-override clear the stream use case override\n" " set-zoom-override <-1/0/1> enable or disable zoom override\n" " Valid values -1: do not override, 0: override to OFF, 1: override to ZOOM\n" + " remap-camera-id remaps camera ids. Must use adb root\n" " watch manages tag monitoring in connected clients\n" " help print this message\n"); } diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 3214d4c475..b9966b3b88 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,7 @@ #include #include #include +#include namespace android { @@ -138,6 +140,9 @@ class CameraService : ///////////////////////////////////////////////////////////////////// // ICameraService + // IMPORTANT: All binder calls that deal with logicalCameraId should use + // resolveCameraId(logicalCameraId) to arrive at the correct cameraId to + // perform the operation on (in case of Id Remapping). virtual binder::Status getNumberOfCameras(int32_t type, int32_t* numCameras); virtual binder::Status getCameraInfo(int cameraId, bool overrideToPortrait, @@ -221,6 +226,9 @@ class CameraService : virtual binder::Status reportExtensionSessionStats( const hardware::CameraExtensionSessionStats& stats, String16* sessionKey /*out*/); + virtual binder::Status remapCameraIds(const hardware::CameraIdRemapping& + cameraIdRemapping); + // Extra permissions checks virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); @@ -916,7 +924,7 @@ class CameraService : int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient, const std::optional& clientFeatureId, int clientUid, int clientPid, apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion, - bool overrideToPortrait, bool forceSlowJpegMode, + bool overrideToPortrait, bool forceSlowJpegMode, const String8& originalCameraId, /*out*/sp& device); // Lock guarding camera service state @@ -943,6 +951,48 @@ class CameraService : // Mutex guarding mCameraStates map mutable Mutex mCameraStatesLock; + /** + * Mapping from packageName -> {cameraIdToReplace -> newCameraIdtoUse}. + * + * This specifies that for packageName, for every binder operation targeting + * cameraIdToReplace, use newCameraIdToUse instead. + */ + typedef std::map> TCameraIdRemapping; + TCameraIdRemapping mCameraIdRemapping{}; + /** Mutex guarding mCameraIdRemapping. */ + Mutex mCameraIdRemappingLock; + + /** Parses cameraIdRemapping parcelable into the native cameraIdRemappingMap. */ + binder::Status parseCameraIdRemapping( + const hardware::CameraIdRemapping& cameraIdRemapping, + TCameraIdRemapping cameraIdRemappingMap); + + /** + * Resolve the (potentially remapped) camera Id to use for packageName. + * + * This returns the Camera Id to use in case inputCameraId was remapped to a + * different Id for the given packageName. Otherwise, it returns the inputCameraId. + */ + String8 resolveCameraId(const String8& inputCameraId, const String16& packageName); + /** + * Resolve the (potentially remapped) camera Id to use. + * + * This returns the Camera Id to use in case inputCameraId was remapped to a + * different Id for the packageName of the client. Otherwise, it returns the inputCameraId. + */ + String8 resolveCameraId(const String8& inputCameraId); + + /** + * Updates the state of mCameraIdRemapping, while disconnecting active clients as necessary. + */ + void remapCameraIds(const TCameraIdRemapping& cameraIdRemapping); + + /** + * Finds the Camera Ids that were remapped to the inputCameraId for the given client. + */ + std::vector findOriginalIdsForRemappedCameraId( + const String8& inputCameraId, int clientUid); + // Circular buffer for storing event logging for dumps RingBuffer mEventLog; Mutex mLogLock; @@ -1322,6 +1372,9 @@ class CameraService : // Set or clear the zoom override flag status_t handleSetZoomOverride(const Vector& args); + // Set Camera Id remapping using 'cmd' + status_t handleCameraIdRemapping(const Vector& args, int errFd); + // Handle 'watch' command as passed through 'cmd' status_t handleWatchCommand(const Vector &args, int inFd, int outFd); @@ -1367,14 +1420,15 @@ class CameraService : */ static String8 getFormattedCurrentTime(); - static binder::Status makeClient(const sp& cameraService, - const sp& cameraCb, const String16& packageName, - bool systemNativeClient, const std::optional& featureId, - const String8& cameraId, int api1CameraId, int facing, int sensorOrientation, - int clientPid, uid_t clientUid, int servicePid, + static binder::Status makeClient( + const sp& cameraService, const sp& cameraCb, + const String16& packageName, bool systemNativeClient, + const std::optional& featureId, const String8& cameraId, int api1CameraId, + int facing, int sensorOrientation, int clientPid, uid_t clientUid, int servicePid, std::pair deviceVersionAndIPCTransport, apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait, bool forceSlowJpegMode, - /*out*/sp* client); + const String8& originalCameraId, + /*out*/ sp* client); status_t checkCameraAccess(const String16& opPackageName); diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp index 38c615d6cc..1720b55aed 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp @@ -98,7 +98,8 @@ CameraDeviceClient::CameraDeviceClient(const sp& cameraService, uid_t clientUid, int servicePid, bool overrideForPerfClass, - bool overrideToPortrait) : + bool overrideToPortrait, + const String8& originalCameraId) : Camera2ClientBase(cameraService, remoteCallback, cameraServiceProxyWrapper, clientPackageName, systemNativeClient, clientFeatureId, cameraId, /*API1 camera ID*/ -1, cameraFacing, sensorOrientation, clientPid, clientUid, servicePid, overrideForPerfClass, @@ -106,8 +107,8 @@ CameraDeviceClient::CameraDeviceClient(const sp& cameraService, mInputStream(), mStreamingRequestId(REQUEST_ID_NONE), mRequestIdCounter(0), - mOverrideForPerfClass(overrideForPerfClass) { - + mOverrideForPerfClass(overrideForPerfClass), + mOriginalCameraId(originalCameraId) { ATRACE_CALL(); ALOGI("CameraDeviceClient %s: Opened", cameraId.string()); } @@ -322,7 +323,7 @@ binder::Status CameraDeviceClient::submitRequestList( //The first capture settings should always match the logical camera id String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str()); - if (mDevice->getId() != logicalId) { + if (mDevice->getId() != logicalId && mOriginalCameraId != logicalId) { ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__, mCameraIdStr.string()); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, @@ -437,6 +438,8 @@ binder::Status CameraDeviceClient::submitRequestList( CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList; for (const auto& it : request.mPhysicalCameraSettings) { + std::string resolvedId = ( + mOriginalCameraId.string() == it.id) ? mDevice->getId().string() : it.id; if (it.settings.isEmpty()) { ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.", __FUNCTION__, mCameraIdStr.string()); @@ -447,7 +450,7 @@ binder::Status CameraDeviceClient::submitRequestList( // Check whether the physical / logical stream has settings // consistent with the sensor pixel mode(s) it was configured with. // mCameraIdToStreamSet will only have ids that are high resolution - const auto streamIdSetIt = mHighResolutionCameraIdToStreamIdSet.find(it.id); + const auto streamIdSetIt = mHighResolutionCameraIdToStreamIdSet.find(resolvedId); if (streamIdSetIt != mHighResolutionCameraIdToStreamIdSet.end()) { std::list streamIdsUsedInRequest = getIntersection(streamIdSetIt->second, outputStreamIds); @@ -455,14 +458,14 @@ binder::Status CameraDeviceClient::submitRequestList( !isSensorPixelModeConsistent(streamIdsUsedInRequest, it.settings)) { ALOGE("%s: Camera %s: Request settings CONTROL_SENSOR_PIXEL_MODE not " "consistent with configured streams. Rejecting request.", - __FUNCTION__, it.id.c_str()); + __FUNCTION__, resolvedId.c_str()); return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Request settings CONTROL_SENSOR_PIXEL_MODE are not consistent with " "streams configured"); } } - String8 physicalId(it.id.c_str()); + String8 physicalId(resolvedId.c_str()); bool hasTestPatternModePhysicalKey = std::find(mSupportedPhysicalRequestKeys.begin(), mSupportedPhysicalRequestKeys.end(), ANDROID_SENSOR_TEST_PATTERN_MODE) != mSupportedPhysicalRequestKeys.end(); @@ -471,7 +474,7 @@ binder::Status CameraDeviceClient::submitRequestList( mSupportedPhysicalRequestKeys.end(); if (physicalId != mDevice->getId()) { auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(), - it.id); + resolvedId); if (found == requestedPhysicalIds.end()) { ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.", __FUNCTION__, mCameraIdStr.string(), physicalId.string()); @@ -494,11 +497,11 @@ binder::Status CameraDeviceClient::submitRequestList( } } - physicalSettingsList.push_back({it.id, filteredParams, + physicalSettingsList.push_back({resolvedId, filteredParams, hasTestPatternModePhysicalKey, hasTestPatternDataPhysicalKey}); } } else { - physicalSettingsList.push_back({it.id, it.settings}); + physicalSettingsList.push_back({resolvedId, it.settings}); } } diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h index 1533cf5745..95563ee529 100644 --- a/services/camera/libcameraservice/api2/CameraDeviceClient.h +++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h @@ -191,7 +191,8 @@ class CameraDeviceClient : uid_t clientUid, int servicePid, bool overrideForPerfClass, - bool overrideToPortrait); + bool overrideToPortrait, + const String8& originalCameraId); virtual ~CameraDeviceClient(); virtual status_t initialize(sp manager, @@ -368,6 +369,9 @@ class CameraDeviceClient : std::string mUserTag; // The last set video stabilization mode int mVideoStabilizationMode = -1; + + // This only exists in case of camera ID Remapping. + String8 mOriginalCameraId; }; }; // namespace android From dc4f375d570965775634d90856719b812aee9865 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 9 Aug 2023 16:21:48 -0700 Subject: [PATCH 091/148] Condition background record restriction on Sdk To prevent breaking existing apps, modify the checks around when an app should have its recording silenced to retain prior behavior unless an app has targetSdk U or greater. Test: oboetester conditionally restricted based on targetSdk level Bug: 268724205 Merged-In: I42b6cbca60db6ce1a073254239b48e9104c4ebfb Change-Id: I42b6cbca60db6ce1a073254239b48e9104c4ebfb --- .../service/AudioPolicyService.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 5d22ed4ce1..15aced0835 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -215,6 +216,27 @@ static void destroyAudioPolicyManager(AudioPolicyInterface *interface) { delete interface; } + +namespace { +int getTargetSdkForPackageName(std::string_view packageName) { + const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); + int targetSdk = -1; + if (binder != nullptr) { + const auto pm = interface_cast(binder); + if (pm != nullptr) { + const auto status = pm->getTargetSdkVersionForPackage( + String16{packageName.data(), packageName.size()}, &targetSdk); + ALOGI("Capy check package %s, sdk %d", packageName.data(), targetSdk); + return status.isOk() ? targetSdk : -1; + } + } + return targetSdk; +} + +bool doesPackageTargetAtLeastU(std::string_view packageName) { + return getTargetSdkForPackageName(packageName) >= __ANDROID_API_U__; +} +} // anonymous // ---------------------------------------------------------------------------- AudioPolicyService::AudioPolicyService() @@ -1926,10 +1948,14 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); + int flags = doesPackageTargetAtLeastU( + mAttributionSource.packageName.value_or("")) ? + AppOpsManager::WATCH_FOREGROUND_CHANGES : 0; // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), + flags, mOpCallback); } From 7e7d3ebb7dd018c3a3a7b00b907488a28353169a Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Thu, 10 Aug 2023 10:12:49 -0600 Subject: [PATCH 092/148] Hide accurate onFrameRendered calls behind render metrics feature flag onFrameRendered calls were modified to be based on present fences, instead of firing immediately after the app releases the buffer to SurfaceFlinger. Hide this modification behind the render metrics feature flag to avoid problems encountered by dogfooders. Bug: 294920725 Test: add log statements to verify legacy mechanism for onFrameRendered calls is switchable with the video render metrics feature flag Change-Id: Ia6f74d8ab72a20eaf167273a1944eddb56f87284 --- media/codec2/sfplugin/CCodecBufferChannel.cpp | 12 +++++++++--- media/codec2/sfplugin/CCodecBufferChannel.h | 1 + media/libstagefright/MediaCodec.cpp | 11 +++++++++-- media/libstagefright/VideoRenderQualityTracker.cpp | 2 +- .../include/media/stagefright/MediaCodec.h | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index d72d228b39..feca03dde9 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -67,6 +67,7 @@ using hardware::hidl_string; using hardware::hidl_vec; using hardware::fromHeap; using hardware::HidlMemory; +using server_configurable_flags::GetServerConfigurableFlag; using namespace hardware::cas::V1_0; using namespace hardware::cas::native::V1_0; @@ -82,6 +83,11 @@ constexpr size_t kSmoothnessFactor = 4; // than making it non-blocking. Do not change this value. const static size_t kDequeueTimeoutNs = 0; +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + } // namespace CCodecBufferChannel::QueueGuard::QueueGuard( @@ -148,6 +154,7 @@ CCodecBufferChannel::CCodecBufferChannel( mCCodecCallback(callback), mFrameIndex(0u), mFirstValidFrameIndex(0u), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), mIsSurfaceToDisplay(false), mHasPresentFenceTimes(false), mRenderingDepth(3u), @@ -174,8 +181,7 @@ CCodecBufferChannel::CCodecBufferChannel( Mutexed::Locked pools(mBlockPools); pools->outputPoolId = C2BlockPool::BASIC_LINEAR; } - std::string value = server_configurable_flags::GetServerConfigurableFlag( - "media_native", "ccodec_rendering_depth", "3"); + std::string value = GetServerConfigurableFlag("media_native", "ccodec_rendering_depth", "3"); android::base::ParseInt(value, &mRenderingDepth); mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + mRenderingDepth; } @@ -996,7 +1002,7 @@ status_t CCodecBufferChannel::renderOutputBuffer( int64_t mediaTimeUs = 0; (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs); - if (mIsSurfaceToDisplay) { + if (mAreRenderMetricsEnabled && mIsSurfaceToDisplay) { trackReleasedFrame(qbo, mediaTimeUs, timestampNs); processRenderedFrames(qbo.frameTimestamps); } else { diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h index 2d87aa94d3..41f5ae2e10 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.h +++ b/media/codec2/sfplugin/CCodecBufferChannel.h @@ -334,6 +334,7 @@ class CCodecBufferChannel sp makeMemoryDealer(size_t heapSize); std::deque mTrackedFrames; + bool mAreRenderMetricsEnabled; bool mIsSurfaceToDisplay; bool mHasPresentFenceTimes; diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index e0ebc1143c..2970aab219 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -92,6 +92,7 @@ using aidl::android::media::BnResourceManagerClient; using aidl::android::media::IResourceManagerClient; using aidl::android::media::IResourceManagerService; using aidl::android::media::ClientInfoParcel; +using server_configurable_flags::GetServerConfigurableFlag; using FreezeEvent = VideoRenderQualityTracker::FreezeEvent; using JudderEvent = VideoRenderQualityTracker::JudderEvent; @@ -282,6 +283,11 @@ static bool isResourceError(status_t err) { return (err == NO_MEMORY); } +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + static const int kMaxRetry = 2; static const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s static const int kNumBuffersAlign = 16; @@ -1025,9 +1031,10 @@ MediaCodec::MediaCodec( mHavePendingInputBuffers(false), mCpuBoostRequested(false), mIsSurfaceToDisplay(false), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), mVideoRenderQualityTracker( VideoRenderQualityTracker::Configuration::getFromServerConfigurableFlags( - server_configurable_flags::GetServerConfigurableFlag)), + GetServerConfigurableFlag)), mLatencyUnknown(0), mBytesEncoded(0), mEarliestEncodedPtsUs(INT64_MAX), @@ -6044,7 +6051,7 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp &msg) { // If rendering to the screen, then schedule a time in the future to poll to see if this // frame was ever rendered to seed onFrameRendered callbacks. - if (mIsSurfaceToDisplay) { + if (mAreRenderMetricsEnabled && mIsSurfaceToDisplay) { if (mediaTimeUs != INT64_MIN) { noRenderTime ? mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs) : mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs, diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp index 4f12a379d4..fbd8577dcf 100644 --- a/media/libstagefright/VideoRenderQualityTracker.cpp +++ b/media/libstagefright/VideoRenderQualityTracker.cpp @@ -154,7 +154,7 @@ VideoRenderQualityTracker::Configuration } VideoRenderQualityTracker::Configuration::Configuration() { - enabled = true; + enabled = false; // Assume that the app is skipping frames because it's detected that the frame couldn't be // rendered in time. diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 52d7d3d36d..163408db2b 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -572,6 +572,7 @@ struct MediaCodec : public AHandler { sp mCryptoLooper; bool mIsSurfaceToDisplay; + bool mAreRenderMetricsEnabled; PlaybackDurationAccumulator mPlaybackDurationAccumulator; VideoRenderQualityTracker mVideoRenderQualityTracker; From d7967a9847931869413a6150d32d563630ff3930 Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Thu, 10 Aug 2023 10:12:49 -0600 Subject: [PATCH 093/148] Hide accurate onFrameRendered calls behind render metrics feature flag onFrameRendered calls were modified to be based on present fences, instead of firing immediately after the app releases the buffer to SurfaceFlinger. Hide this modification behind the render metrics feature flag to avoid problems encountered by dogfooders. Bug: 294920725 Test: add log statements to verify legacy mechanism for onFrameRendered calls is switchable with the video render metrics feature flag Change-Id: Ia6f74d8ab72a20eaf167273a1944eddb56f87284 --- media/codec2/sfplugin/CCodecBufferChannel.cpp | 12 +++++++++--- media/codec2/sfplugin/CCodecBufferChannel.h | 1 + media/libstagefright/ACodec.cpp | 13 ++++++++++++- media/libstagefright/MediaCodec.cpp | 11 +++++++++-- media/libstagefright/VideoRenderQualityTracker.cpp | 2 +- .../include/media/stagefright/ACodec.h | 8 +++++--- .../include/media/stagefright/MediaCodec.h | 1 + 7 files changed, 38 insertions(+), 10 deletions(-) diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index d72d228b39..feca03dde9 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -67,6 +67,7 @@ using hardware::hidl_string; using hardware::hidl_vec; using hardware::fromHeap; using hardware::HidlMemory; +using server_configurable_flags::GetServerConfigurableFlag; using namespace hardware::cas::V1_0; using namespace hardware::cas::native::V1_0; @@ -82,6 +83,11 @@ constexpr size_t kSmoothnessFactor = 4; // than making it non-blocking. Do not change this value. const static size_t kDequeueTimeoutNs = 0; +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + } // namespace CCodecBufferChannel::QueueGuard::QueueGuard( @@ -148,6 +154,7 @@ CCodecBufferChannel::CCodecBufferChannel( mCCodecCallback(callback), mFrameIndex(0u), mFirstValidFrameIndex(0u), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), mIsSurfaceToDisplay(false), mHasPresentFenceTimes(false), mRenderingDepth(3u), @@ -174,8 +181,7 @@ CCodecBufferChannel::CCodecBufferChannel( Mutexed::Locked pools(mBlockPools); pools->outputPoolId = C2BlockPool::BASIC_LINEAR; } - std::string value = server_configurable_flags::GetServerConfigurableFlag( - "media_native", "ccodec_rendering_depth", "3"); + std::string value = GetServerConfigurableFlag("media_native", "ccodec_rendering_depth", "3"); android::base::ParseInt(value, &mRenderingDepth); mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + mRenderingDepth; } @@ -996,7 +1002,7 @@ status_t CCodecBufferChannel::renderOutputBuffer( int64_t mediaTimeUs = 0; (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs); - if (mIsSurfaceToDisplay) { + if (mAreRenderMetricsEnabled && mIsSurfaceToDisplay) { trackReleasedFrame(qbo, mediaTimeUs, timestampNs); processRenderedFrames(qbo.frameTimestamps); } else { diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h index 2d87aa94d3..41f5ae2e10 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.h +++ b/media/codec2/sfplugin/CCodecBufferChannel.h @@ -334,6 +334,7 @@ class CCodecBufferChannel sp makeMemoryDealer(size_t heapSize); std::deque mTrackedFrames; + bool mAreRenderMetricsEnabled; bool mIsSurfaceToDisplay; bool mHasPresentFenceTimes; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 2bc8c96de1..d506ee54a8 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -65,11 +65,14 @@ #include "include/SharedMemoryBuffer.h" #include +#include + namespace android { typedef hardware::media::omx::V1_0::IGraphicBufferSource HGraphicBufferSource; using hardware::media::omx::V1_0::Status; +using server_configurable_flags::GetServerConfigurableFlag; enum { kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles @@ -82,6 +85,11 @@ constexpr char TUNNEL_PEEK_SET_LEGACY_KEY[] = "android._tunnel-peek-set-legacy"; } +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + // OMX errors are directly mapped into status_t range if // there is no corresponding MediaError status code. // Use the statusFromOMXError(int32_t omxError) function. @@ -562,6 +570,9 @@ void ACodec::BufferInfo::checkReadFence(const char *dbg) { ACodec::ACodec() : mSampleRate(0), mNodeGeneration(0), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), + mIsWindowToDisplay(false), + mHasPresentFenceTimes(false), mUsingNativeWindow(false), mNativeWindowUsageBits(0), mLastNativeWindowDataSpace(HAL_DATASPACE_UNKNOWN), @@ -6808,7 +6819,7 @@ void ACodec::BaseState::onOutputBufferDrained(const sp &msg) { int64_t mediaTimeUs = -1; buffer->meta()->findInt64("timeUs", &mediaTimeUs); - if (mCodec->mIsWindowToDisplay) { + if (mCodec->mAreRenderMetricsEnabled && mCodec->mIsWindowToDisplay) { mCodec->trackReleasedFrame(frameId, mediaTimeUs, timestampNs); mCodec->pollForRenderedFrames(); } else { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 463f212db6..d9a226e7b3 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -93,6 +93,7 @@ using aidl::android::media::BnResourceManagerClient; using aidl::android::media::IResourceManagerClient; using aidl::android::media::IResourceManagerService; using aidl::android::media::ClientInfoParcel; +using server_configurable_flags::GetServerConfigurableFlag; using FreezeEvent = VideoRenderQualityTracker::FreezeEvent; using JudderEvent = VideoRenderQualityTracker::JudderEvent; @@ -283,6 +284,11 @@ static bool isResourceError(status_t err) { return (err == NO_MEMORY); } +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + static const int kMaxRetry = 2; static const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s static const int kNumBuffersAlign = 16; @@ -1026,9 +1032,10 @@ MediaCodec::MediaCodec( mHavePendingInputBuffers(false), mCpuBoostRequested(false), mIsSurfaceToDisplay(false), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), mVideoRenderQualityTracker( VideoRenderQualityTracker::Configuration::getFromServerConfigurableFlags( - server_configurable_flags::GetServerConfigurableFlag)), + GetServerConfigurableFlag)), mLatencyUnknown(0), mBytesEncoded(0), mEarliestEncodedPtsUs(INT64_MAX), @@ -6055,7 +6062,7 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp &msg) { // If rendering to the screen, then schedule a time in the future to poll to see if this // frame was ever rendered to seed onFrameRendered callbacks. - if (mIsSurfaceToDisplay) { + if (mAreRenderMetricsEnabled && mIsSurfaceToDisplay) { if (mediaTimeUs != INT64_MIN) { noRenderTime ? mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs) : mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs, diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp index 4f12a379d4..fbd8577dcf 100644 --- a/media/libstagefright/VideoRenderQualityTracker.cpp +++ b/media/libstagefright/VideoRenderQualityTracker.cpp @@ -154,7 +154,7 @@ VideoRenderQualityTracker::Configuration } VideoRenderQualityTracker::Configuration::Configuration() { - enabled = true; + enabled = false; // Assume that the app is skipping frames because it's detected that the frame couldn't be // rendered in time. diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h index 88cff23281..49b2425177 100644 --- a/media/libstagefright/include/media/stagefright/ACodec.h +++ b/media/libstagefright/include/media/stagefright/ACodec.h @@ -258,10 +258,13 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { int32_t mNodeGeneration; sp mAllocator[2]; - bool mUsingNativeWindow; - sp mNativeWindow; + std::deque mTrackedFrames; // render information for buffers sent to a window + bool mAreRenderMetricsEnabled; bool mIsWindowToDisplay; bool mHasPresentFenceTimes; + + bool mUsingNativeWindow; + sp mNativeWindow; int mNativeWindowUsageBits; android_native_rect_t mLastNativeWindowCrop; int32_t mLastNativeWindowDataSpace; @@ -276,7 +279,6 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { // format updates. This will equal to mOutputFormat until the first actual frame is received. sp mBaseOutputFormat; - std::deque mTrackedFrames; // render information for buffers sent to a window std::vector mBuffers[2]; bool mPortEOS[2]; status_t mInputEOSResult; diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 6c2a0969d2..36084db027 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -575,6 +575,7 @@ struct MediaCodec : public AHandler { sp mCryptoLooper; bool mIsSurfaceToDisplay; + bool mAreRenderMetricsEnabled; PlaybackDurationAccumulator mPlaybackDurationAccumulator; VideoRenderQualityTracker mVideoRenderQualityTracker; From 0230540dbcefd8c9d0e73a423ad95f3ad379c3a0 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 10 May 2023 21:37:41 -0700 Subject: [PATCH 094/148] Correct attribution source for MMAP thread Ensure that the package name, which is used for listening for appops below getInputForAttr, is corrected for MMAP threads. Bug: 268724205 Test: AudioRecordTest Test: Oboetester MMAP record silenced when backgrounded - 6s (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f59db5cb1be38abce4c3c4f553090e527a6d4513) Merged-In: Ia6fc1bff815bbbb2fee8bc1a60569a663a713e4b Change-Id: Ia6fc1bff815bbbb2fee8bc1a60569a663a713e4b --- services/audioflinger/Threads.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 683e320073..964f4d0036 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -9509,6 +9509,9 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t io = mId; + AttributionSourceState adjAttributionSource = AudioFlinger::checkAttributionSourcePackage( + client.attributionSource); + if (isOutput()) { audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = mSampleRate; @@ -9523,7 +9526,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, ret = AudioSystem::getOutputForAttr(&mAttr, &io, mSessionId, &stream, - client.attributionSource, + adjAttributionSource, &config, flags, &deviceId, @@ -9541,7 +9544,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, ret = AudioSystem::getInputForAttr(&mAttr, &io, RECORD_RIID_INVALID, mSessionId, - client.attributionSource, + adjAttributionSource, &config, AUDIO_INPUT_FLAG_MMAP_NOIRQ, &deviceId, From 5be19e855d2a9b772d43aacf0af2848d862a1b90 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 10 May 2023 21:37:41 -0700 Subject: [PATCH 095/148] Correct attribution source for MMAP thread Ensure that the package name, which is used for listening for appops below getInputForAttr, is corrected for MMAP threads. Bug: 268724205 Test: AudioRecordTest Test: Oboetester MMAP record silenced when backgrounded - 6s (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f59db5cb1be38abce4c3c4f553090e527a6d4513) Merged-In: Ia6fc1bff815bbbb2fee8bc1a60569a663a713e4b Change-Id: Ia6fc1bff815bbbb2fee8bc1a60569a663a713e4b --- services/audioflinger/Threads.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 7f2680014d..0c0c618e99 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -9188,6 +9188,9 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE; audio_io_handle_t io = mId; + AttributionSourceState adjAttributionSource = AudioFlinger::checkAttributionSourcePackage( + client.attributionSource); + if (isOutput()) { audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = mSampleRate; @@ -9201,7 +9204,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, ret = AudioSystem::getOutputForAttr(&mAttr, &io, mSessionId, &stream, - client.attributionSource, + adjAttributionSource, &config, flags, &deviceId, @@ -9218,7 +9221,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client, ret = AudioSystem::getInputForAttr(&mAttr, &io, RECORD_RIID_INVALID, mSessionId, - client.attributionSource, + adjAttributionSource, &config, AUDIO_INPUT_FLAG_MMAP_NOIRQ, &deviceId, From 6a61bc6be41e97eace472fdb6eb25a1bbaec7c5e Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Mon, 10 Jul 2023 20:27:41 -0700 Subject: [PATCH 096/148] APC: Wake OffloadThread on AppOps mute Bug: 289885996 Test: atest AudioPlaybackConfigurationTest with setprop audio.offload.min.duration.secs 1 Merged-In: I93c3a507eb3f9146ff8d80ce5f34ea0e46a49e5a Change-Id: I93c3a507eb3f9146ff8d80ce5f34ea0e46a49e5a (cherry picked from commit 9d7c6f8f6649574362e087641a7b50805294a07c) --- services/audioflinger/PlaybackTracks.h | 10 ++++- services/audioflinger/Tracks.cpp | 53 +++++++++++++++----------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index d485ccc387..302ae2e200 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -23,18 +23,21 @@ // Checks and monitors OP_PLAY_AUDIO class OpPlayAudioMonitor : public RefBase { + friend class sp; public: ~OpPlayAudioMonitor() override; bool hasOpPlayAudio() const; static sp createIfNeeded( + AudioFlinger::ThreadBase* thread, const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id, audio_stream_type_t streamType); private: - OpPlayAudioMonitor(const AttributionSourceState& attributionSource, - audio_usage_t usage, int id); + OpPlayAudioMonitor(AudioFlinger::ThreadBase* thread, + const AttributionSourceState& attributionSource, + audio_usage_t usage, int id, uid_t uid); void onFirstRef() override; static void getPackagesForUid(uid_t uid, Vector& packages); @@ -53,10 +56,13 @@ class OpPlayAudioMonitor : public RefBase { // called by PlayAudioOpCallback when OP_PLAY_AUDIO is updated in AppOp callback void checkPlayAudioForUsage(); + wp mThread; std::atomic_bool mHasOpPlayAudio; const AttributionSourceState mAttributionSource; const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t const int mId; // for logging purposes only + const uid_t mUid; + const String16 mPackageName; }; // playback track diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 7f99599e80..730d73d313 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -506,11 +506,12 @@ Status AudioFlinger::TrackHandle::setPlaybackRateParameters( // static sp AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded( + AudioFlinger::ThreadBase* thread, const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id, audio_stream_type_t streamType) { - Vector packages; - uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); + Vector packages; + const uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); getPackagesForUid(uid, packages); if (isServiceUid(uid)) { if (packages.isEmpty()) { @@ -532,15 +533,21 @@ AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded( id, attr.flags); return nullptr; } - return new OpPlayAudioMonitor(attributionSource, attr.usage, id); + return sp::make(thread, attributionSource, attr.usage, id, uid); } AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor( - const AttributionSourceState& attributionSource, audio_usage_t usage, int id) - : mHasOpPlayAudio(true), mAttributionSource(attributionSource), mUsage((int32_t) usage), - mId(id) -{ -} + AudioFlinger::ThreadBase* thread, + const AttributionSourceState& attributionSource, + audio_usage_t usage, int id, uid_t uid) + : mThread(wp::fromExisting(thread)), + mHasOpPlayAudio(true), + mAttributionSource(attributionSource), + mUsage((int32_t)usage), + mId(id), + mUid(uid), + mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16( + attributionSource.packageName.value_or("")))) {} AudioFlinger::PlaybackThread::OpPlayAudioMonitor::~OpPlayAudioMonitor() { @@ -556,9 +563,7 @@ void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef() if (mAttributionSource.packageName.has_value()) { mOpCallback = new PlayAudioOpCallback(this); mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, - VALUE_OR_FATAL(aidl2legacy_string_view_String16( - mAttributionSource.packageName.value_or(""))) - , mOpCallback); + mPackageName, mOpCallback); } } @@ -571,16 +576,20 @@ bool AudioFlinger::PlaybackThread::OpPlayAudioMonitor::hasOpPlayAudio() const { // - not called from PlayAudioOpCallback because the callback is not installed in this case void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage() { - if (!mAttributionSource.packageName.has_value()) { - mHasOpPlayAudio.store(false); - } else { - uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mAttributionSource.uid)); - String16 packageName = VALUE_OR_FATAL( - aidl2legacy_string_view_String16(mAttributionSource.packageName.value_or(""))); - bool hasIt = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO, - mUsage, uid, packageName) == AppOpsManager::MODE_ALLOWED; - ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasIt ? "not " : ""); - mHasOpPlayAudio.store(hasIt); + const bool hasAppOps = mAttributionSource.packageName.has_value() + && mAppOpsManager.checkAudioOpNoThrow( + AppOpsManager::OP_PLAY_AUDIO, mUsage, mUid, mPackageName) == + AppOpsManager::MODE_ALLOWED; + + bool shouldChange = !hasAppOps; // check if we need to update. + if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) { + ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : ""); + auto thread = mThread.promote(); + if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) { + // Wake up Thread if offloaded, otherwise it may be several seconds for update. + Mutex::Autolock _l(thread->mLock); + thread->broadcast_l(); + } } } @@ -658,7 +667,7 @@ AudioFlinger::PlaybackThread::Track::Track( mAuxEffectId(0), mHasVolumeController(false), mFrameMap(16 /* sink-frame-to-track-frame map memory */), mVolumeHandler(new media::VolumeHandler(sampleRate)), - mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(attributionSource, attr, id(), + mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(thread, attributionSource, attr, id(), streamType)), // mSinkTimestamp mFastIndex(-1), From e8773c703603bea5220af1e0d6725c58e293f13c Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Wed, 2 Aug 2023 18:36:04 -0700 Subject: [PATCH 097/148] APC: Add possible deadlock fix when creating track When creating a new track the thread lock is being held. This can have the effect of causing a deadlock when the OpPlayAudioMonitor is being created since the onFirstRef method could also try to access the same thread lock. Removing the broadcast when calling onFirstRef which is not needed and would also avoid the deadlock Test: atest AudioPlaybackConfigurationTest Bug: 289885996 Merged-In: I16555608176f1b1dfa180e82346319b55c19de01 Change-Id: I16555608176f1b1dfa180e82346319b55c19de01 --- services/audioflinger/PlaybackTracks.h | 2 +- services/audioflinger/Tracks.cpp | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 302ae2e200..57655d55a0 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -54,7 +54,7 @@ class OpPlayAudioMonitor : public RefBase { sp mOpCallback; // called by PlayAudioOpCallback when OP_PLAY_AUDIO is updated in AppOp callback - void checkPlayAudioForUsage(); + void checkPlayAudioForUsage(bool doBroadcast); wp mThread; std::atomic_bool mHasOpPlayAudio; diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 730d73d313..ec5fbdaaf4 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -559,7 +559,9 @@ AudioFlinger::PlaybackThread::OpPlayAudioMonitor::~OpPlayAudioMonitor() void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef() { - checkPlayAudioForUsage(); + // make sure not to broadcast the initial state since it is not needed and could + // cause a deadlock since this method can be called with the mThread->mLock held + checkPlayAudioForUsage(/*doBroadcast=*/false); if (mAttributionSource.packageName.has_value()) { mOpCallback = new PlayAudioOpCallback(this); mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO, @@ -574,7 +576,7 @@ bool AudioFlinger::PlaybackThread::OpPlayAudioMonitor::hasOpPlayAudio() const { // Note this method is never called (and never to be) for audio server / patch record track // - not called from constructor due to check on UID, // - not called from PlayAudioOpCallback because the callback is not installed in this case -void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage() +void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast) { const bool hasAppOps = mAttributionSource.packageName.has_value() && mAppOpsManager.checkAudioOpNoThrow( @@ -584,11 +586,13 @@ void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage() bool shouldChange = !hasAppOps; // check if we need to update. if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) { ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : ""); - auto thread = mThread.promote(); - if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) { - // Wake up Thread if offloaded, otherwise it may be several seconds for update. - Mutex::Autolock _l(thread->mLock); - thread->broadcast_l(); + if (doBroadcast) { + auto thread = mThread.promote(); + if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) { + // Wake up Thread if offloaded, otherwise it may be several seconds for update. + Mutex::Autolock _l(thread->mLock); + thread->broadcast_l(); + } } } } @@ -606,7 +610,7 @@ void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::PlayAudioOpCallback::opCh } sp monitor = mMonitor.promote(); if (monitor != NULL) { - monitor->checkPlayAudioForUsage(); + monitor->checkPlayAudioForUsage(/*doBroadcast=*/true); } } From 214f6e62d77ddad430ebbb15854ac9852d9ee5c8 Mon Sep 17 00:00:00 2001 From: malikakash Date: Thu, 10 Aug 2023 23:50:56 +0000 Subject: [PATCH 098/148] Harden remapCameraApi() API - Pluralize list fields, it is easier to work with. - Change String[] to List. This has no effect on the cpp handling, it just makes the java client code easier to work with. - Check against more edge cases. - Fix small bug in parsing found after E2E testing (pass argument by reference) Bug: 286287541 Test: Tested the binder calls using custom service. Was able to trigger all edge cases. Change-Id: I9dedf5aeace3ac7da32b6a362c1fc9c7fd7c98ce Merged-In: I176959e56563bc587c4fca594cfc242941b503d6 --- .../android/hardware/CameraIdRemapping.aidl | 10 +++---- .../camera/libcameraservice/CameraService.cpp | 30 +++++++++++++------ .../camera/libcameraservice/CameraService.h | 4 +-- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/camera/aidl/android/hardware/CameraIdRemapping.aidl b/camera/aidl/android/hardware/CameraIdRemapping.aidl index ab0a39ce1b..e875c53526 100644 --- a/camera/aidl/android/hardware/CameraIdRemapping.aidl +++ b/camera/aidl/android/hardware/CameraIdRemapping.aidl @@ -35,16 +35,16 @@ parcelable CameraIdRemapping { * Ordered list of Camera Ids to replace. Only Camera Ids present in this list will be * affected. */ - String[] cameraIdToReplace; + List cameraIdsToReplace; /** - * Ordered list of updated Camera Ids, where updatedCameraId[i] corresponds to - * the updated camera id for cameraIdToReplace[i]. + * Ordered list of updated Camera Ids, where updatedCameraIds[i] corresponds to + * the updated camera id for cameraIdsToReplace[i]. */ - String[] updatedCameraId; + List updatedCameraIds; } /** * List of Camera Id remappings to perform. */ - List packageIdRemapping; + List packageIdRemappings; } diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 7551bd793b..9f52ddf20b 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -766,7 +766,7 @@ Status CameraService::remapCameraIds(const hardware::CameraIdRemapping& "Permission Denial: no permission to configure camera id mapping"); } TCameraIdRemapping cameraIdRemappingMap{}; - binder::Status parseStatus = parseCameraIdRemapping(cameraIdRemapping, cameraIdRemappingMap); + binder::Status parseStatus = parseCameraIdRemapping(cameraIdRemapping, &cameraIdRemappingMap); if (!parseStatus.isOk()) { return parseStatus; } @@ -776,25 +776,37 @@ Status CameraService::remapCameraIds(const hardware::CameraIdRemapping& Status CameraService::parseCameraIdRemapping( const hardware::CameraIdRemapping& cameraIdRemapping, - TCameraIdRemapping cameraIdRemappingMap) { + /* out */ TCameraIdRemapping* cameraIdRemappingMap) { String16 packageName; String8 cameraIdToReplace, updatedCameraId; - for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemapping) { + for(const auto& packageIdRemapping: cameraIdRemapping.packageIdRemappings) { packageName = packageIdRemapping.packageName; if (packageName == String16("")) { return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "CameraIdRemapping: Package name cannot be empty"); } - if (packageIdRemapping.cameraIdToReplace.size() - != packageIdRemapping.updatedCameraId.size()) { + + if (packageIdRemapping.cameraIdsToReplace.size() + != packageIdRemapping.updatedCameraIds.size()) { return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "CameraIdRemapping: Mismatch in CameraId Remapping lists sizes for package %s", String8(packageName).c_str()); } - for(size_t i = 0; i < packageIdRemapping.cameraIdToReplace.size(); i++) { - cameraIdToReplace = String8(packageIdRemapping.cameraIdToReplace[i]); - updatedCameraId = String8(packageIdRemapping.updatedCameraId[i]); - cameraIdRemappingMap[packageName][cameraIdToReplace] = updatedCameraId; + for(size_t i = 0; i < packageIdRemapping.cameraIdsToReplace.size(); i++) { + cameraIdToReplace = String8(packageIdRemapping.cameraIdsToReplace[i]); + updatedCameraId = String8(packageIdRemapping.updatedCameraIds[i]); + if (cameraIdToReplace == String8("") || updatedCameraId == String8("")) { + return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, + "CameraIdRemapping: Camera Id cannot be empty for package %s", + String8(packageName).c_str()); + } + if (cameraIdToReplace == updatedCameraId) { + return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, + "CameraIdRemapping: CameraIdToReplace cannot be the same" + " as updatedCameraId for %s", + String8(packageName).c_str()); + } + (*cameraIdRemappingMap)[packageName][cameraIdToReplace] = updatedCameraId; } } return Status::ok(); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index b9966b3b88..65b11e7f29 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -964,8 +964,8 @@ class CameraService : /** Parses cameraIdRemapping parcelable into the native cameraIdRemappingMap. */ binder::Status parseCameraIdRemapping( - const hardware::CameraIdRemapping& cameraIdRemapping, - TCameraIdRemapping cameraIdRemappingMap); + const hardware::CameraIdRemapping& cameraIdRemapping, + /* out */ TCameraIdRemapping* cameraIdRemappingMap); /** * Resolve the (potentially remapped) camera Id to use for packageName. From 31a428aa84ecd03141f02b413d5520551da6e511 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 11 Aug 2023 12:16:28 +0200 Subject: [PATCH 099/148] audio policy: fix BT SCO volume issue SwAudioOutputDescriptor::setVolume has a provision to duplicate stream BT SCO volume changes to stream VOICE_CALL. But this was done wihtout updating the current set volume for the voice call volume source causing further updates to voice call volume to be ignored if they happened to have the same value as the stored value. Bug: 293241158 Test: repro steps in bug Change-Id: I978ff03ffd4ff07306176bb98f41388761305185 --- .../include/AudioOutputDescriptor.h | 25 +++++++++++++++---- .../src/AudioOutputDescriptor.cpp | 19 +++++++++----- .../managerdefault/AudioPolicyManager.cpp | 4 +-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index febccac3e6..1e57edd5bc 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -102,9 +102,13 @@ class VolumeActivity : public ActivityTracking void setVolume(float volumeDb) { mCurVolumeDb = volumeDb; } float getVolume() const { return mCurVolumeDb; } + void setIsVoice(bool isVoice) { mIsVoice = isVoice; } + bool isVoice() const { return mIsVoice; } + private: int mMuteCount = 0; /**< mute request counter */ float mCurVolumeDb = NAN; /**< current volume in dB. */ + bool mIsVoice = false; /** true if this volume source is used for voice call volume */ }; /** * Note: volume activities shall be indexed by CurvesId if we want to allow multiple @@ -162,7 +166,8 @@ class AudioOutputDescriptor: public AudioPortConfig, VolumeSource volumeSource, const StreamTypeVector &streams, const DeviceTypeSet& deviceTypes, uint32_t delayMs, - bool force); + bool force, + bool isVoiceVolSrc = false); /** * @brief setStopTime set the stop time due to the client stoppage or a re routing of this @@ -222,17 +227,25 @@ class AudioOutputDescriptor: public AudioPortConfig, { return mVolumeActivities[vs].decMuteCount(); } - void setCurVolume(VolumeSource vs, float volumeDb) + void setCurVolume(VolumeSource vs, float volumeDb, bool isVoiceVolSrc) { // Even if not activity for this source registered, need to create anyway mVolumeActivities[vs].setVolume(volumeDb); + mVolumeActivities[vs].setIsVoice(isVoiceVolSrc); } float getCurVolume(VolumeSource vs) const { return mVolumeActivities.find(vs) != std::end(mVolumeActivities) ? mVolumeActivities.at(vs).getVolume() : NAN; } - + VolumeSource getVoiceSource() { + for (const auto &iter : mVolumeActivities) { + if (iter.second.isVoice()) { + return iter.first; + } + } + return VOLUME_SOURCE_NONE; + } bool isStrategyActive(product_strategy_t ps, uint32_t inPastMs = 0, nsecs_t sysTime = 0) const { return mRoutingActivities.find(ps) != std::end(mRoutingActivities)? @@ -381,7 +394,8 @@ class SwAudioOutputDescriptor: public AudioOutputDescriptor VolumeSource volumeSource, const StreamTypeVector &streams, const DeviceTypeSet& device, uint32_t delayMs, - bool force); + bool force, + bool isVoiceVolSrc = false); virtual void toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig = NULL) const; @@ -484,7 +498,8 @@ class HwAudioOutputDescriptor: public AudioOutputDescriptor VolumeSource volumeSource, const StreamTypeVector &streams, const DeviceTypeSet& deviceTypes, uint32_t delayMs, - bool force); + bool force, + bool isVoiceVolSrc = false); virtual void toAudioPortConfig(struct audio_port_config *dstConfig, const struct audio_port_config *srcConfig = NULL) const; diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 8b2331112e..2f424b8d46 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -163,7 +163,8 @@ bool AudioOutputDescriptor::setVolume(float volumeDb, bool /*muted*/, const StreamTypeVector &/*streams*/, const DeviceTypeSet& deviceTypes, uint32_t delayMs, - bool force) + bool force, + bool isVoiceVolSrc) { if (!supportedDevices().containsDeviceAmongTypes(deviceTypes)) { @@ -176,7 +177,7 @@ bool AudioOutputDescriptor::setVolume(float volumeDb, bool /*muted*/, // - the force flag is set if (volumeDb != getCurVolume(volumeSource) || force) { ALOGV("%s for volumeSrc %d, volume %f, delay %d", __func__, volumeSource, volumeDb, delayMs); - setCurVolume(volumeSource, volumeDb); + setCurVolume(volumeSource, volumeDb, isVoiceVolSrc); return true; } return false; @@ -510,11 +511,12 @@ bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool muted, VolumeSource vs, const StreamTypeVector &streamTypes, const DeviceTypeSet& deviceTypes, uint32_t delayMs, - bool force) + bool force, + bool isVoiceVolSrc) { StreamTypeVector streams = streamTypes; if (!AudioOutputDescriptor::setVolume( - volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force)) { + volumeDb, muted, vs, streamTypes, deviceTypes, delayMs, force, isVoiceVolSrc)) { return false; } if (streams.empty()) { @@ -560,6 +562,10 @@ bool SwAudioOutputDescriptor::setVolume(float volumeDb, bool muted, float volumeAmpl = Volume::DbToAmpl(getCurVolume(vs)); if (hasStream(streams, AUDIO_STREAM_BLUETOOTH_SCO)) { mClientInterface->setStreamVolume(AUDIO_STREAM_VOICE_CALL, volumeAmpl, mIoHandle, delayMs); + VolumeSource callVolSrc = getVoiceSource(); + if (callVolSrc != VOLUME_SOURCE_NONE) { + setCurVolume(callVolSrc, getCurVolume(vs), true); + } } for (const auto &stream : streams) { ALOGV("%s output %d for volumeSource %d, volume %f, delay %d stream=%s", __func__, @@ -788,10 +794,11 @@ bool HwAudioOutputDescriptor::setVolume(float volumeDb, bool muted, VolumeSource volumeSource, const StreamTypeVector &streams, const DeviceTypeSet& deviceTypes, uint32_t delayMs, - bool force) + bool force, + bool isVoiceVolSrc) { bool changed = AudioOutputDescriptor::setVolume( - volumeDb, muted, volumeSource, streams, deviceTypes, delayMs, force); + volumeDb, muted, volumeSource, streams, deviceTypes, delayMs, force, isVoiceVolSrc); if (changed) { // TODO: use gain controller on source device if any to adjust volume diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index b17177dcb6..8717083c3e 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -7836,8 +7836,8 @@ status_t AudioPolicyManager::checkAndSetVolume(IVolumeCurves &curves, volumeDb = 0.0f; } const bool muted = (index == 0) && (volumeDb != 0.0f); - outputDesc->setVolume( - volumeDb, muted, volumeSource, curves.getStreamTypes(), deviceTypes, delayMs, force); + outputDesc->setVolume(volumeDb, muted, volumeSource, curves.getStreamTypes(), + deviceTypes, delayMs, force, isVoiceVolSrc); if (outputDesc == mPrimaryOutput && (isVoiceVolSrc || isBtScoVolSrc)) { float voiceVolume; From 95a5258312d9adef8a6dda01d3f69148bf5005aa Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Thu, 10 Aug 2023 10:12:49 -0600 Subject: [PATCH 100/148] Hide accurate onFrameRendered calls behind render metrics feature flag onFrameRendered calls were modified to be based on present fences, instead of firing immediately after the app releases the buffer to SurfaceFlinger. Hide this modification behind the render metrics feature flag to avoid problems encountered by dogfooders. Bug: 294920725 Test: add log statements to verify legacy mechanism for onFrameRendered calls is switchable with the video render metrics feature flag Change-Id: Ia6f74d8ab72a20eaf167273a1944eddb56f87284 --- media/codec2/sfplugin/CCodecBufferChannel.cpp | 12 +++++++++--- media/codec2/sfplugin/CCodecBufferChannel.h | 1 + media/libstagefright/MediaCodec.cpp | 11 +++++++++-- media/libstagefright/VideoRenderQualityTracker.cpp | 2 +- .../include/media/stagefright/MediaCodec.h | 1 + 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index d72d228b39..feca03dde9 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -67,6 +67,7 @@ using hardware::hidl_string; using hardware::hidl_vec; using hardware::fromHeap; using hardware::HidlMemory; +using server_configurable_flags::GetServerConfigurableFlag; using namespace hardware::cas::V1_0; using namespace hardware::cas::native::V1_0; @@ -82,6 +83,11 @@ constexpr size_t kSmoothnessFactor = 4; // than making it non-blocking. Do not change this value. const static size_t kDequeueTimeoutNs = 0; +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + } // namespace CCodecBufferChannel::QueueGuard::QueueGuard( @@ -148,6 +154,7 @@ CCodecBufferChannel::CCodecBufferChannel( mCCodecCallback(callback), mFrameIndex(0u), mFirstValidFrameIndex(0u), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), mIsSurfaceToDisplay(false), mHasPresentFenceTimes(false), mRenderingDepth(3u), @@ -174,8 +181,7 @@ CCodecBufferChannel::CCodecBufferChannel( Mutexed::Locked pools(mBlockPools); pools->outputPoolId = C2BlockPool::BASIC_LINEAR; } - std::string value = server_configurable_flags::GetServerConfigurableFlag( - "media_native", "ccodec_rendering_depth", "3"); + std::string value = GetServerConfigurableFlag("media_native", "ccodec_rendering_depth", "3"); android::base::ParseInt(value, &mRenderingDepth); mOutputSurface.lock()->maxDequeueBuffers = kSmoothnessFactor + mRenderingDepth; } @@ -996,7 +1002,7 @@ status_t CCodecBufferChannel::renderOutputBuffer( int64_t mediaTimeUs = 0; (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs); - if (mIsSurfaceToDisplay) { + if (mAreRenderMetricsEnabled && mIsSurfaceToDisplay) { trackReleasedFrame(qbo, mediaTimeUs, timestampNs); processRenderedFrames(qbo.frameTimestamps); } else { diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h index 2d87aa94d3..41f5ae2e10 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.h +++ b/media/codec2/sfplugin/CCodecBufferChannel.h @@ -334,6 +334,7 @@ class CCodecBufferChannel sp makeMemoryDealer(size_t heapSize); std::deque mTrackedFrames; + bool mAreRenderMetricsEnabled; bool mIsSurfaceToDisplay; bool mHasPresentFenceTimes; diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index e0ebc1143c..2970aab219 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -92,6 +92,7 @@ using aidl::android::media::BnResourceManagerClient; using aidl::android::media::IResourceManagerClient; using aidl::android::media::IResourceManagerService; using aidl::android::media::ClientInfoParcel; +using server_configurable_flags::GetServerConfigurableFlag; using FreezeEvent = VideoRenderQualityTracker::FreezeEvent; using JudderEvent = VideoRenderQualityTracker::JudderEvent; @@ -282,6 +283,11 @@ static bool isResourceError(status_t err) { return (err == NO_MEMORY); } +static bool areRenderMetricsEnabled() { + std::string v = GetServerConfigurableFlag("media_native", "render_metrics_enabled", "false"); + return v == "true"; +} + static const int kMaxRetry = 2; static const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s static const int kNumBuffersAlign = 16; @@ -1025,9 +1031,10 @@ MediaCodec::MediaCodec( mHavePendingInputBuffers(false), mCpuBoostRequested(false), mIsSurfaceToDisplay(false), + mAreRenderMetricsEnabled(areRenderMetricsEnabled()), mVideoRenderQualityTracker( VideoRenderQualityTracker::Configuration::getFromServerConfigurableFlags( - server_configurable_flags::GetServerConfigurableFlag)), + GetServerConfigurableFlag)), mLatencyUnknown(0), mBytesEncoded(0), mEarliestEncodedPtsUs(INT64_MAX), @@ -6044,7 +6051,7 @@ status_t MediaCodec::onReleaseOutputBuffer(const sp &msg) { // If rendering to the screen, then schedule a time in the future to poll to see if this // frame was ever rendered to seed onFrameRendered callbacks. - if (mIsSurfaceToDisplay) { + if (mAreRenderMetricsEnabled && mIsSurfaceToDisplay) { if (mediaTimeUs != INT64_MIN) { noRenderTime ? mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs) : mVideoRenderQualityTracker.onFrameReleased(mediaTimeUs, diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp index 4f12a379d4..fbd8577dcf 100644 --- a/media/libstagefright/VideoRenderQualityTracker.cpp +++ b/media/libstagefright/VideoRenderQualityTracker.cpp @@ -154,7 +154,7 @@ VideoRenderQualityTracker::Configuration } VideoRenderQualityTracker::Configuration::Configuration() { - enabled = true; + enabled = false; // Assume that the app is skipping frames because it's detected that the frame couldn't be // rendered in time. diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h index 52d7d3d36d..163408db2b 100644 --- a/media/libstagefright/include/media/stagefright/MediaCodec.h +++ b/media/libstagefright/include/media/stagefright/MediaCodec.h @@ -572,6 +572,7 @@ struct MediaCodec : public AHandler { sp mCryptoLooper; bool mIsSurfaceToDisplay; + bool mAreRenderMetricsEnabled; PlaybackDurationAccumulator mPlaybackDurationAccumulator; VideoRenderQualityTracker mVideoRenderQualityTracker; From 4c88e716ff40ad6e7e0e30ea5dab5712606df4c3 Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Tue, 8 Aug 2023 12:35:45 -0600 Subject: [PATCH 101/148] Add last video render time to bug reports The last video render time can be helpful for detecting the point in time around which a permanent video freeze occurs, allowing one to pinpoint in system logs other events occurring around that point in time. Bug: 293851202 Bug: 295565737 Test: play a video that freezes (see bug) and look at metrics Change-Id: I4ee46120c825c7e1b7a394e4f20cd5c710a63bc1 --- media/libstagefright/MediaCodec.cpp | 2 ++ media/libstagefright/VideoRenderQualityTracker.cpp | 2 ++ .../include/media/stagefright/VideoRenderQualityTracker.h | 3 +++ 3 files changed, 7 insertions(+) diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 463f212db6..04cc113e95 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -210,6 +210,7 @@ static const char *kCodecShapingEnhanced = "android.media.mediacodec.shaped"; // Render metrics static const char *kCodecPlaybackDurationSec = "android.media.mediacodec.playback-duration-sec"; static const char *kCodecFirstRenderTimeUs = "android.media.mediacodec.first-render-time-us"; +static const char *kCodecLastRenderTimeUs = "android.media.mediacodec.last-render-time-us"; static const char *kCodecFramesReleased = "android.media.mediacodec.frames-released"; static const char *kCodecFramesRendered = "android.media.mediacodec.frames-rendered"; static const char *kCodecFramesDropped = "android.media.mediacodec.frames-dropped"; @@ -1168,6 +1169,7 @@ void MediaCodec::updateMediametrics() { const VideoRenderQualityMetrics &m = mVideoRenderQualityTracker.getMetrics(); if (m.frameReleasedCount > 0) { mediametrics_setInt64(mMetricsHandle, kCodecFirstRenderTimeUs, m.firstRenderTimeUs); + mediametrics_setInt64(mMetricsHandle, kCodecLastRenderTimeUs, m.lastRenderTimeUs); mediametrics_setInt64(mMetricsHandle, kCodecFramesReleased, m.frameReleasedCount); mediametrics_setInt64(mMetricsHandle, kCodecFramesRendered, m.frameRenderedCount); mediametrics_setInt64(mMetricsHandle, kCodecFramesSkipped, m.frameSkippedCount); diff --git a/media/libstagefright/VideoRenderQualityTracker.cpp b/media/libstagefright/VideoRenderQualityTracker.cpp index 4f12a379d4..dba49c115e 100644 --- a/media/libstagefright/VideoRenderQualityTracker.cpp +++ b/media/libstagefright/VideoRenderQualityTracker.cpp @@ -455,6 +455,8 @@ void VideoRenderQualityTracker::processMetricsForRenderedFrame(int64_t contentTi if (mMetrics.firstRenderTimeUs == 0) { mMetrics.firstRenderTimeUs = actualRenderTimeUs; } + // Capture the timestamp at which the last frame was rendered + mMetrics.lastRenderTimeUs = actualRenderTimeUs; mMetrics.frameRenderedCount++; diff --git a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h index 82ba81caa1..a656e6e90b 100644 --- a/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h +++ b/media/libstagefright/include/media/stagefright/VideoRenderQualityTracker.h @@ -38,6 +38,9 @@ struct VideoRenderQualityMetrics { // The render time of the first video frame. int64_t firstRenderTimeUs; + // The render time of the last video frame. + int64_t lastRenderTimeUs; + // The number of frames released to be rendered. int64_t frameReleasedCount; From e285845148fcd2872a7fbcfbcf7c6b839425e673 Mon Sep 17 00:00:00 2001 From: Jaideep Sharma Date: Mon, 14 Aug 2023 13:03:18 +0530 Subject: [PATCH 102/148] av: Fix command/setParameter for inactive subEffects Fix the code to send command, setParameters for inactive subeffects. With current conditional, if active subeffect is at index 0 then all other subeffects won't be iterated. Fix by running over all items and then skipping for active index. Bug: 295787396 Test: Enable aidl and test with YTM Change-Id: I49a794fa121c5b78b239906067b95572d84bc0c3 Merged-In: I49a794fa121c5b78b239906067b95572d84bc0c3 --- media/libaudiohal/impl/EffectProxy.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index cb5b4b9544..f0c9686cd7 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -232,7 +232,10 @@ ndk::ScopedAStatus EffectProxy::runWithActiveSubEffectThenOthers( } // proceed with others - for (size_t i = 0; i < mSubEffects.size() && i != mActiveSubIdx; i++) { + for (size_t i = 0; i < mSubEffects.size(); i++) { + if (i == mActiveSubIdx) { + continue; + } if (!mSubEffects[i].handle) { ALOGE("%s null sub-effect interface for %s", __func__, mSubEffects[i].descriptor.common.id.uuid.toString().c_str()); From 0efe2b4d6b739650039c2cab176ef11d5f5ac49c Mon Sep 17 00:00:00 2001 From: Venkatarama Avadhani Date: Fri, 11 Aug 2023 15:19:24 +0000 Subject: [PATCH 103/148] Initialise VPS buffer to NULL in constructor Missing initialisation of this pointer could lead to an incorrect free if the ARTWriter object is cleared immeddiately after the constructor call. Bug: 287298721 Test: rtp_writer_fuzzer (cherry picked from https://partner-android-review.googlesource.com/q/commit:2710696b001f2e95586151c1ee337a4e3c4da48a) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:900195c1d3589c7cbf9e116f61bebaefc0519101) Merged-In: I08eacd7a0201bc9a41b821e20cae916d8870147a Change-Id: I08eacd7a0201bc9a41b821e20cae916d8870147a --- media/libstagefright/rtsp/ARTPWriter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp index 11c7aeb9fc..1e08606407 100644 --- a/media/libstagefright/rtsp/ARTPWriter.cpp +++ b/media/libstagefright/rtsp/ARTPWriter.cpp @@ -105,6 +105,7 @@ ARTPWriter::ARTPWriter(int fd) mRTCPAddr = mRTPAddr; mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1); + mVPSBuf = NULL; mSPSBuf = NULL; mPPSBuf = NULL; From 0c92078954acc7b658859509e612ccf51ec20883 Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Wed, 9 Aug 2023 11:21:22 -0700 Subject: [PATCH 104/148] CSD: Disable the forced use of framework MEL The vendors can decide whether to use the sound dose feature and are responsible for ensuring that the sound dose HAL is present for modules that support offloading. It is ok to fall back to the internal framework MEL computation when a CSD HAL is not implemented. This will however not guarantee a certification with the EN50332-3 and IEC62368-1 3rd edition regulation. Test: manual CSD enablement Bug: 287011781 Merged-In: If6a6f47a408020011fcb7a4af2dbd0c0121b1c86 Change-Id: If6a6f47a408020011fcb7a4af2dbd0c0121b1c86 --- services/audioflinger/sounddose/SoundDoseManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h index 718913d6a1..42a793dc9e 100644 --- a/services/audioflinger/sounddose/SoundDoseManager.h +++ b/services/audioflinger/sounddose/SoundDoseManager.h @@ -244,7 +244,7 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { std::shared_ptr mHalSoundDose GUARDED_BY(mLock); std::shared_ptr mHalSoundDoseCallback GUARDED_BY(mLock); - bool mUseFrameworkMel GUARDED_BY(mLock) = true; + bool mUseFrameworkMel GUARDED_BY(mLock) = false; bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false; bool mEnabledCsd GUARDED_BY(mLock) = true; From f97b08a4448b50f56581880143b94c618ecb6a6b Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Wed, 16 Aug 2023 16:24:59 -0700 Subject: [PATCH 105/148] CSD: fix test after reverting the force MEL flag. With ag/24453728 we reverted the flag so the test needs to be adjusted too. Test: atest sounddosemanager_test Bug: 296297753 Merged-In: I53e1bb7b900628e5715beefa2ceee93b299127bc Change-Id: I53e1bb7b900628e5715beefa2ceee93b299127bc --- .../audioflinger/sounddose/tests/sounddosemanager_tests.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp index 7d0b3a76ff..5860d96949 100644 --- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp +++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp @@ -248,8 +248,7 @@ TEST_F(SoundDoseManagerTest, GetDefaultForceComputeCsdOnAllDevices) { } TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) { - // TODO: for now dogfooding with internal MEL. Revert to false when using the HAL MELs - EXPECT_TRUE(mSoundDoseManager->forceUseFrameworkMel()); + EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel()); } TEST_F(SoundDoseManagerTest, SetAudioDeviceCategoryStopsNonHeadphone) { From c195254f405eeedb98e02078cc9754fee36b1f5b Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Mon, 14 Aug 2023 20:48:37 +0000 Subject: [PATCH 106/148] Send effect device/mode/source update if indicator was set in descriptor Bug: 271500140 Test: Enable AIDL and test with YTM Test: atest EffectsFactoryHalInterfaceTest Change-Id: Ie85c2101eb37f2835d6e9e91a0ecc9273a250a0e Merged-In: Ie85c2101eb37f2835d6e9e91a0ecc9273a250a0e --- .../impl/EffectConversionHelperAidl.cpp | 45 ++++++++++++++++++- .../impl/EffectConversionHelperAidl.h | 3 +- media/libaudiohal/impl/EffectHalAidl.cpp | 8 ++-- media/libaudiohal/impl/EffectHalAidl.h | 1 - media/libaudiohal/impl/EffectProxy.cpp | 6 --- .../tests/EffectsFactoryHalInterface_test.cpp | 39 ++++++++++++++++ 6 files changed, 88 insertions(+), 14 deletions(-) diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp index 049c3585c6..5dcc08b4f6 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -62,6 +63,7 @@ const std::map - // const auto& legacyDevice = *(uint32_t*)(pCmdData); + if (!getDescriptor().common.flags.deviceIndication) { + ALOGW("%s parameter no deviceIndication, skipping", __func__); + return OK; + } + // convert from bitmask of audio_devices_t to std::vector + auto legacyDevices = *(uint32_t*)(pCmdData); + // extract the input bit and remove it from bitmasks + const auto inputBit = legacyDevices & AUDIO_DEVICE_BIT_IN; + legacyDevices &= ~AUDIO_DEVICE_BIT_IN; std::vector aidlDevices; + while (legacyDevices) { + // get audio_devices_t represented by the last true bit and convert to AIDL + const auto lowestBitDevice = legacyDevices & -legacyDevices; + AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS( + ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription( + static_cast(lowestBitDevice | inputBit))); + aidlDevices.emplace_back(deviceDesc); + legacyDevices -= lowestBitDevice; + } + RETURN_STATUS_IF_ERROR(statusTFromBinderStatus( mEffect->setParameter(Parameter::make(aidlDevices)))); return *static_cast(pReplyData) = OK; @@ -436,5 +463,19 @@ bool EffectConversionHelperAidl::isBypassing() const { (mIsProxyEffect && std::static_pointer_cast(mEffect)->isBypassing())); } +Descriptor EffectConversionHelperAidl::getDescriptor() const { + if (!mIsProxyEffect) { + return mDesc; + } + + Descriptor desc; + if (const auto status = mEffect->getDescriptor(&desc); !status.isOk()) { + ALOGE("%s failed to get proxy descriptor (%d:%s), using default", __func__, + status.getStatus(), status.getMessage()); + return mDesc; + } + return desc; +} + } // namespace effect } // namespace android diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h index 7c8f11b481..85e877e2f0 100644 --- a/media/libaudiohal/impl/EffectConversionHelperAidl.h +++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h @@ -43,6 +43,8 @@ class EffectConversionHelperAidl { std::shared_ptr getEventFlagGroup() { return mEfGroup; } bool isBypassing() const; + ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const; + protected: const int32_t mSessionId; const int32_t mIoId; @@ -134,7 +136,6 @@ class EffectConversionHelperAidl { virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) { return BAD_VALUE; } - }; } // namespace effect diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp index 2d9e155a35..97cdb6af45 100644 --- a/media/libaudiohal/impl/EffectHalAidl.cpp +++ b/media/libaudiohal/impl/EffectHalAidl.cpp @@ -69,7 +69,6 @@ EffectHalAidl::EffectHalAidl(const std::shared_ptr& factory, mEffect(effect), mSessionId(sessionId), mIoId(ioId), - mDesc(desc), mIsProxyEffect(isProxyEffect) { createAidlConversion(effect, sessionId, ioId, desc); } @@ -169,7 +168,8 @@ status_t EffectHalAidl::process() { State state = State::INIT; if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() || state != State::PROCESSING) { - ALOGI("%s skipping %s process because it's %s", __func__, mDesc.common.name.c_str(), + ALOGI("%s skipping %s process because it's %s", __func__, + mConversion->getDescriptor().common.name.c_str(), mConversion->isBypassing() ? "bypassing" : aidl::android::hardware::audio::effect::toString(state).c_str()); @@ -225,8 +225,8 @@ status_t EffectHalAidl::process() { return INVALID_OPERATION; } - ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite, - floatsToRead); + ALOGD("%s %s consumed %zu produced %zu", __func__, + mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead); return OK; } diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h index 1b7a3d6166..bbcb7e2965 100644 --- a/media/libaudiohal/impl/EffectHalAidl.h +++ b/media/libaudiohal/impl/EffectHalAidl.h @@ -72,7 +72,6 @@ class EffectHalAidl : public EffectHalInterface { const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect; const int32_t mSessionId; const int32_t mIoId; - const ::aidl::android::hardware::audio::effect::Descriptor mDesc; const bool mIsProxyEffect; std::unique_ptr mConversion; diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp index f0c9686cd7..3c5c68645c 100644 --- a/media/libaudiohal/impl/EffectProxy.cpp +++ b/media/libaudiohal/impl/EffectProxy.cpp @@ -169,12 +169,6 @@ Descriptor::Common EffectProxy::buildDescriptorCommon( common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL; } - // initial flag values before we know which sub-effect to active (with setOffloadParam) - // same as HIDL EffectProxy flags - common.flags.type = Flags::Type::INSERT; - common.flags.insert = Flags::Insert::LAST; - common.flags.volume = Flags::Volume::NONE; - // set indication if any sub-effect indication was set common.flags.offloadIndication |= desc.common.flags.offloadIndication; common.flags.deviceIndication |= desc.common.flags.deviceIndication; diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp index 2854496255..0cb654c13b 100644 --- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp +++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp @@ -347,6 +347,45 @@ TEST_P(libAudioHalEffectParamTest, setAndGetParam) { } } +TEST_P(libAudioHalEffectParamTest, deviceIndicationUpdate) { + for (auto& interface : mHalInterfaces) { + EXPECT_NO_FATAL_FAILURE(initEffect(interface)); + + // output device + uint32_t deviceTypes = AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_BLE_SPEAKER; + status_t cmdStatus; + uint32_t replySize = sizeof(cmdStatus); + EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes, + &replySize, &cmdStatus)); + // input device + deviceTypes = AUDIO_DEVICE_IN_WIRED_HEADSET | AUDIO_DEVICE_IN_BLUETOOTH_BLE; + EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_DEVICE, sizeof(uint32_t), &deviceTypes, + &replySize, &cmdStatus)); + } +} + +TEST_P(libAudioHalEffectParamTest, audioModeIndicationUpdate) { + for (auto& interface : mHalInterfaces) { + EXPECT_NO_FATAL_FAILURE(initEffect(interface)); + uint32_t mode = AUDIO_MODE_IN_CALL; + status_t cmdStatus; + uint32_t replySize = sizeof(cmdStatus); + EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_MODE, sizeof(uint32_t), &mode, + &replySize, &cmdStatus)); + } +} + +TEST_P(libAudioHalEffectParamTest, audioSourceIndicationUpdate) { + for (auto& interface : mHalInterfaces) { + EXPECT_NO_FATAL_FAILURE(initEffect(interface)); + uint32_t source = AUDIO_SOURCE_MIC; + status_t cmdStatus; + uint32_t replySize = sizeof(cmdStatus); + EXPECT_EQ(OK, interface->command(EFFECT_CMD_SET_AUDIO_SOURCE, sizeof(uint32_t), &source, + &replySize, &cmdStatus)); + } +} + INSTANTIATE_TEST_SUITE_P( libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs), [](const testing::TestParamInfo& info) { From d3283e9159cd8228864f4f6b7550cef0c89bfae6 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Thu, 10 Aug 2023 12:52:14 -0700 Subject: [PATCH 107/148] AIDL: Consider both inputs and output of r_submix to be "virtual" Since the AIDL implementation of the remote submix does support "connect external device" operation, the framework uses it to assign a device address to a remote submix pipe. Thus, we should treat both inputs and outputs as "virtual" connections, that is, they need to be connected explicitly, however they don't require a physical device. Bug: 286914845 Bug: 294976817 Test: live caption scenario Change-Id: I0e5d13e03ebf0d466080f83cc9373906e9affa36 Merged-In: I0e5d13e03ebf0d466080f83cc9373906e9affa36 --- media/audioaidlconversion/AidlConversionCppNdk.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp index 4d3f9bd15e..7ea51ff873 100644 --- a/media/audioaidlconversion/AidlConversionCppNdk.cpp +++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp @@ -508,15 +508,6 @@ const detail::AudioDevicePairs& getAudioDevicePairs() { { AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription( AudioDeviceType::IN_ECHO_REFERENCE) - }, - { - AUDIO_DEVICE_IN_REMOTE_SUBMIX, make_AudioDeviceDescription( - AudioDeviceType::IN_SUBMIX) - }, - { - AUDIO_DEVICE_OUT_REMOTE_SUBMIX, make_AudioDeviceDescription( - AudioDeviceType::OUT_SUBMIX, - GET_DEVICE_DESC_CONNECTION(VIRTUAL)) } }}; append_AudioDeviceDescription(pairs, @@ -592,6 +583,11 @@ const detail::AudioDevicePairs& getAudioDevicePairs() { AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET, AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET, GET_DEVICE_DESC_CONNECTION(BT_LE)); + append_AudioDeviceDescription(pairs, + AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX, + AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX, + GET_DEVICE_DESC_CONNECTION(VIRTUAL)); + return pairs; }(); return pairs; From 92b7af019c74c55764fccb69f490d3b4d051e26e Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Mon, 21 Aug 2023 08:32:00 -0700 Subject: [PATCH 108/148] AIDL: Fix test after aosp/2704653 That change updated the connection for the "remote submix in" device type, however the test was not updated, resulting in a failure. The need to modify the test was overlooked because the TEST_MAPPING file for the library was wrong, although syntacsically correct. Fix the mapping file to prevent future regressions. Bug: 286914845 Bug: 294976817 Bug: 296664539 Test: audio_aidl_conversion_tests Change-Id: I3bcfab9ca45c19d487deb7709d32f43beee8c789 Merged-In: I3bcfab9ca45c19d487deb7709d32f43beee8c789 --- media/audioaidlconversion/TEST_MAPPING | 8 ++++++-- .../tests/audio_aidl_legacy_conversion_tests.cpp | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING index 216bc12dab..203ed2f9c8 100644 --- a/media/audioaidlconversion/TEST_MAPPING +++ b/media/audioaidlconversion/TEST_MAPPING @@ -1,8 +1,12 @@ { "presubmit": [ { - "name": "audio_aidl_conversion_tests", - "name": "audio_aidl_ndk_conversion_tests", + "name": "audio_aidl_conversion_tests" + }, + { + "name": "audio_aidl_ndk_conversion_tests" + }, + { "name": "audio_aidl_ndk_cpp_conversion_tests" } ] diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp index 976a532133..9a46b20116 100644 --- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp +++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp @@ -143,7 +143,8 @@ AudioDeviceDescription make_ADD_MicIn() { } AudioDeviceDescription make_ADD_RSubmixIn() { - return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX); + return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX, + AudioDeviceDescription::CONNECTION_VIRTUAL()); } AudioDeviceDescription make_ADD_DefaultOut() { From 733ab192011df7afc48a7f4d88ed1a960e264608 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 9 Aug 2023 16:21:48 -0700 Subject: [PATCH 109/148] Condition background record restriction on Sdk To prevent breaking existing apps, modify the checks around when an app should have its recording silenced to retain prior behavior unless an app has targetSdk U or greater. Test: oboetester conditionally restricted based on targetSdk level Bug: 268724205 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc4f375d570965775634d90856719b812aee9865) Merged-In: I42b6cbca60db6ce1a073254239b48e9104c4ebfb Change-Id: I42b6cbca60db6ce1a073254239b48e9104c4ebfb --- .../service/AudioPolicyService.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index df0c59f6fa..889ae960ca 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -202,6 +203,26 @@ static void destroyAudioPolicyManager(AudioPolicyInterface *interface) { delete interface; } + +namespace { +int getTargetSdkForPackageName(std::string_view packageName) { + const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); + int targetSdk = -1; + if (binder != nullptr) { + const auto pm = interface_cast(binder); + if (pm != nullptr) { + const auto status = pm->getTargetSdkVersionForPackage( + String16{packageName.data(), packageName.size()}, &targetSdk); + return status.isOk() ? targetSdk : -1; + } + } + return targetSdk; +} + +bool doesPackageTargetAtLeastU(std::string_view packageName) { + return getTargetSdkForPackageName(packageName) >= __ANDROID_API_U__; +} +} // anonymous // ---------------------------------------------------------------------------- AudioPolicyService::AudioPolicyService() @@ -1913,10 +1934,14 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); + int flags = doesPackageTargetAtLeastU( + mAttributionSource.packageName.value_or("")) ? + AppOpsManager::WATCH_FOREGROUND_CHANGES : 0; // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), + flags, mOpCallback); } From 3de585db623429900c684c12ad4ac17fb78979b0 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 9 Aug 2023 16:21:48 -0700 Subject: [PATCH 110/148] Condition background record restriction on Sdk To prevent breaking existing apps, modify the checks around when an app should have its recording silenced to retain prior behavior unless an app has targetSdk U or greater. Test: oboetester conditionally restricted based on targetSdk level Bug: 268724205 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc4f375d570965775634d90856719b812aee9865) Merged-In: I42b6cbca60db6ce1a073254239b48e9104c4ebfb Change-Id: I42b6cbca60db6ce1a073254239b48e9104c4ebfb --- .../service/AudioPolicyService.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index e7d945fad6..926d7f013d 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -192,6 +193,27 @@ static void destroyAudioPolicyManager(AudioPolicyInterface *interface) { delete interface; } + +namespace { +int getTargetSdkForPackageName(std::string_view packageName) { + const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); + int targetSdk = -1; + if (binder != nullptr) { + const auto pm = interface_cast(binder); + if (pm != nullptr) { + const auto status = pm->getTargetSdkVersionForPackage( + String16{packageName.data(), packageName.size()}, &targetSdk); + return status.isOk() ? targetSdk : -1; + } + } + return targetSdk; +} + +bool doesPackageTargetAtLeastU(std::string_view packageName) { + constexpr int ANDROID_API_U = 34; + return getTargetSdkForPackageName(packageName) >= ANDROID_API_U; +} +} // anonymous // ---------------------------------------------------------------------------- AudioPolicyService::AudioPolicyService() @@ -1873,10 +1895,14 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); + int flags = doesPackageTargetAtLeastU( + mAttributionSource.packageName.value_or("")) ? + AppOpsManager::WATCH_FOREGROUND_CHANGES : 0; // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), + flags, mOpCallback); } From 382a9eaf46cf53b986494a694c9a87b8be8a28e4 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 9 Aug 2023 16:21:48 -0700 Subject: [PATCH 111/148] Condition background record restriction on Sdk To prevent breaking existing apps, modify the checks around when an app should have its recording silenced to retain prior behavior unless an app has targetSdk U or greater. Test: oboetester conditionally restricted based on targetSdk level Bug: 268724205 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dc4f375d570965775634d90856719b812aee9865) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:a5ed2002773feb3dd371cc473fc0a6ff2dfd21b6) Merged-In: I42b6cbca60db6ce1a073254239b48e9104c4ebfb Change-Id: I42b6cbca60db6ce1a073254239b48e9104c4ebfb --- .../service/AudioPolicyService.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 4d0e1f12a6..eb6666165d 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -77,6 +78,27 @@ static void destroyAudioPolicyManager(AudioPolicyInterface *interface) { delete interface; } + +namespace { +int getTargetSdkForPackageName(std::string_view packageName) { + const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); + int targetSdk = -1; + if (binder != nullptr) { + const auto pm = interface_cast(binder); + if (pm != nullptr) { + const auto status = pm->getTargetSdkVersionForPackage( + String16{packageName.data(), packageName.size()}, &targetSdk); + return status.isOk() ? targetSdk : -1; + } + } + return targetSdk; +} + +bool doesPackageTargetAtLeastU(std::string_view packageName) { + constexpr int ANDROID_API_U = 34; + return getTargetSdkForPackageName(packageName) >= ANDROID_API_U; +} +} // anonymous // ---------------------------------------------------------------------------- AudioPolicyService::AudioPolicyService() @@ -1482,10 +1504,14 @@ void AudioPolicyService::OpRecordAudioMonitor::onFirstRef() checkOp(); mOpCallback = new RecordAudioOpCallback(this); ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str()); + int flags = doesPackageTargetAtLeastU( + mAttributionSource.packageName.value_or("")) ? + AppOpsManager::WATCH_FOREGROUND_CHANGES : 0; // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too // since it controls the mic permission for legacy apps. mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16( mAttributionSource.packageName.value_or(""))), + flags, mOpCallback); } From 272071ed785d29a5c8ebd4a0afce1f0ba1a4751c Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Wed, 23 Aug 2023 18:31:08 +0000 Subject: [PATCH 112/148] Remove accidental debug log line Remove accidental debug line in dc4f375d570965775634d90856719b812aee9865 Bug: 268724205 Change-Id: I385d1262c75b81c96c4644e0415fa138b131d96c Merged-In: I42b6cbca60db6ce1a073254239b48e9104c4ebfb Test: Compiles --- services/audiopolicy/service/AudioPolicyService.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 15aced0835..4620a2e9a7 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -226,7 +226,6 @@ int getTargetSdkForPackageName(std::string_view packageName) { if (pm != nullptr) { const auto status = pm->getTargetSdkVersionForPackage( String16{packageName.data(), packageName.size()}, &targetSdk); - ALOGI("Capy check package %s, sdk %d", packageName.data(), targetSdk); return status.isOk() ? targetSdk : -1; } } From 7aa76cedc006500e4db1e5084c77b6183d8bac35 Mon Sep 17 00:00:00 2001 From: Atneya Nair Date: Mon, 12 Jun 2023 15:32:49 -0700 Subject: [PATCH 113/148] [RESTRICT AUTOMERGE] Update uid state based on capability field Use the passed capability field in the to prevent clients from recording in the background. To work around existing issues in the implementation, the approach is - if we don't hold the capability, simulate an onUidIdle. - if we hold the capability, to simulate an onUidActive and then the existing behavior (update the AM state). Only update behavior for apps targetSdk > 34. Bug: 268724205 Test: OboeTester recording silenced in background for all paths Test: OboeTester recording permitted after returning to foreground Test: AGSA works Test: atest AudioRecordTest Change-Id: Ida37fec306417b40006dfac5b5ed04f17418b7c8 --- .../service/AudioPolicyService.cpp | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index e847f9f9c9..2bfeb61416 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -21,9 +21,11 @@ #undef __STRICT_ANSI__ #define __STDINT_LIMITS #define __STDC_LIMIT_MACROS +#include #include #include +#include #include #include #include @@ -54,6 +56,37 @@ static const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds static const String16 sManageAudioPolicyPermission("android.permission.MANAGE_AUDIO_POLICY"); +namespace { +int getTargetSdkForPackageName(String16 packageName) { + const auto binder = defaultServiceManager()->checkService(String16{"package_native"}); + int targetSdk = -1; + if (binder != nullptr) { + const auto pm = interface_cast(binder); + if (pm != nullptr) { + const auto status = pm->getTargetSdkVersionForPackage(packageName, &targetSdk); + ALOGI("Capy check package %s, sdk %d", String8(packageName).string(), targetSdk); + return status.isOk() ? targetSdk : -1; + } + } + return targetSdk; +} + +bool doesUidTargetAtLeastU(uid_t uid) { + Vector packages; + PermissionController pc; + pc.getPackagesForUid(uid, packages); + constexpr int ANDROID_API_U = 34; + return packages.empty() || (getTargetSdkForPackageName(packages[0]) >= ANDROID_API_U); +} + +bool doesUidTargetAtLeastUCached(uid_t uid) { + static std::map cache; + const auto it = cache.find(uid); + return it == cache.end() ? (cache[uid] = doesUidTargetAtLeastU(uid)) : it->second; +} + + +} // anonymous // ---------------------------------------------------------------------------- AudioPolicyService::AudioPolicyService() @@ -1054,9 +1087,29 @@ void AudioPolicyService::UidPolicy::onUidIdle(uid_t uid, __unused bool disabled) void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq __unused, - int32_t capability __unused) { + int32_t capability) { if (procState != ActivityManager::PROCESS_STATE_UNKNOWN) { - updateUid(&mCachedUids, uid, true, procState, true); + if (doesUidTargetAtLeastUCached(uid)) { + // See ActivityManager.java + constexpr int32_t PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2; + if (capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) { + // The implementation relies on the assumption that this callback is preceded by + // onUidActive. This may not be the case if we have lost and then regained the + // capability, since we simulate onUidIdle below. So, we simulate onUidActive. + // In the typical case where we haven't regained capability, this is a no-op, since + // we should've been preceded by an onUidActive callback anyway. + updateUid(&mCachedUids, uid, true /* active */, + ActivityManager::PROCESS_STATE_UNKNOWN, true /* insert */); + updateUid(&mCachedUids, uid, true /* active */, procState, true /* insert */); + } else { + // If we have lost the capability (e.g. moving to background), treat as-if we have + // gotten onUidIdle. + updateUid(&mCachedUids, uid, false /* active */, + ActivityManager::PROCESS_STATE_UNKNOWN, true /* insert */); + } + } else { + updateUid(&mCachedUids, uid, true, procState, true); + } } } From 08c8c4b8ab60934e37db9bbd1f5adf0b149d99ef Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Mon, 21 Aug 2023 19:52:14 -0700 Subject: [PATCH 114/148] CSD: add support for multiple sound dose HALs Initial implementation to support multiple sound dose HALs. Also not falling back to internal MELs in case one module is not supporting the sound dose HAL Test: manual + atest sounddosemanager_tests Bug: 297057693 Merged-In: I7941e34c08496781f4393358d1ce2845d525b86c Change-Id: I7941e34c08496781f4393358d1ce2845d525b86c --- services/audioflinger/MelReporter.cpp | 15 ++-- .../sounddose/SoundDoseManager.cpp | 83 +++++++++++-------- .../audioflinger/sounddose/SoundDoseManager.h | 19 +++-- .../tests/sounddosemanager_tests.cpp | 32 +++++-- 4 files changed, 96 insertions(+), 53 deletions(-) diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp index 3af882813c..23dfb7ff56 100644 --- a/services/audioflinger/MelReporter.cpp +++ b/services/audioflinger/MelReporter.cpp @@ -38,24 +38,21 @@ bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::strin ndk::SpAIBinder soundDoseBinder; if (device->getSoundDoseInterface(module, &soundDoseBinder) != OK) { - ALOGW("%s: HAL cannot provide sound dose interface for module %s, use internal MEL", + ALOGW("%s: HAL cannot provide sound dose interface for module %s", __func__, module.c_str()); - activateInternalSoundDoseComputation(); return false; } if (soundDoseBinder == nullptr) { - ALOGW("%s: HAL doesn't implement a sound dose interface for module %s, use internal MEL", + ALOGW("%s: HAL doesn't implement a sound dose interface for module %s", __func__, module.c_str()); - activateInternalSoundDoseComputation(); return false; } std::shared_ptr soundDoseInterface = ISoundDose::fromBinder(soundDoseBinder); - if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) { + if (!mSoundDoseManager->setHalSoundDoseInterface(module, soundDoseInterface)) { ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str()); - activateInternalSoundDoseComputation(); return false; } @@ -73,7 +70,8 @@ void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() { mUseHalSoundDoseInterface = false; } - mSoundDoseManager->setHalSoundDoseInterface(nullptr); + // reset the HAL interfaces and use internal MELs + mSoundDoseManager->resetHalSoundDoseInterfaces(); } void AudioFlinger::MelReporter::onFirstRef() { @@ -251,6 +249,9 @@ sp AudioFlinger::MelReporter::getSoundDoseInterface( void AudioFlinger::MelReporter::stopInternalMelComputation() { ALOGV("%s", __func__); std::lock_guard _l(mLock); + if (mUseHalSoundDoseInterface) { + return; + } mActiveMelPatches.clear(); mUseHalSoundDoseInterface = true; } diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp index a551857716..697d028b30 100644 --- a/services/audioflinger/sounddose/SoundDoseManager.cpp +++ b/services/audioflinger/sounddose/SoundDoseManager.cpp @@ -50,7 +50,7 @@ sp SoundDoseManager::getOrCreateProcessorForDevice( size_t channelCount, audio_format_t format) { std::lock_guard _l(mLock); - if (mHalSoundDose != nullptr && mEnabledCsd) { + if (mHalSoundDose.size() > 0 && mEnabledCsd) { ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__); return nullptr; } @@ -83,19 +83,27 @@ sp SoundDoseManager::getOrCreateProcessorForDevice( return melProcessor; } -bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr& halSoundDose) { +bool SoundDoseManager::setHalSoundDoseInterface(const std::string &module, + const std::shared_ptr &halSoundDose) { ALOGV("%s", __func__); + if (halSoundDose == nullptr) { + ALOGI("%s: passed ISoundDose object is null", __func__); + return false; + } + + std::shared_ptr halSoundDoseCallback; { std::lock_guard _l(mLock); - mHalSoundDose = halSoundDose; - if (halSoundDose == nullptr) { - ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__); + if (mHalSoundDose.find(module) != mHalSoundDose.end()) { + ALOGW("%s: Module %s already has a sound dose HAL assigned, skipping", __func__, + module.c_str()); return false; } + mHalSoundDose[module] = halSoundDose; - if (!mHalSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) { + if (!halSoundDose->setOutputRs2UpperBound(mRs2UpperBound).isOk()) { ALOGW("%s: Cannot set RS2 value for momentary exposure %f", __func__, mRs2UpperBound); @@ -119,16 +127,26 @@ bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptrsetOutputRs2UpperBound(rs2Value).isOk()) { - ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value); - return; + if (mHalSoundDose.size() > 0) { + for (auto& halSoundDose : mHalSoundDose) { + // using the HAL sound dose interface + if (!halSoundDose.second->setOutputRs2UpperBound(rs2Value).isOk()) { + ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, rs2Value); + continue; + } } + mRs2UpperBound = rs2Value; return; } @@ -200,14 +218,16 @@ void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) { ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning( float in_currentDbA, const AudioDevice& in_audioDevice) { - auto soundDoseManager = mSoundDoseManager.promote(); - if (soundDoseManager == nullptr) { - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + sp soundDoseManager; + { + const std::lock_guard _l(mCbLock); + soundDoseManager = mSoundDoseManager.promote(); + if (soundDoseManager == nullptr) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } } - std::shared_ptr halSoundDose; - soundDoseManager->getHalSoundDose(&halSoundDose); - if(halSoundDose == nullptr) { + if (!soundDoseManager->useHalSoundDose()) { ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } @@ -227,14 +247,16 @@ ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWa ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues( const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord, const AudioDevice& in_audioDevice) { - auto soundDoseManager = mSoundDoseManager.promote(); - if (soundDoseManager == nullptr) { - return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + sp soundDoseManager; + { + const std::lock_guard _l(mCbLock); + soundDoseManager = mSoundDoseManager.promote(); + if (soundDoseManager == nullptr) { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); + } } - std::shared_ptr halSoundDose; - soundDoseManager->getHalSoundDose(&halSoundDose); - if(halSoundDose == nullptr) { + if (!soundDoseManager->useHalSoundDose()) { ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE); } @@ -508,7 +530,7 @@ bool SoundDoseManager::shouldComputeCsdForDeviceWithAddress(const audio_devices_ void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) { // invalidate any HAL sound dose interface used - setHalSoundDoseInterface(nullptr); + resetHalSoundDoseInterfaces(); std::lock_guard _l(mLock); mUseFrameworkMel = useFrameworkMel; @@ -534,17 +556,12 @@ bool SoundDoseManager::isSoundDoseHalSupported() const { return false; } - std::shared_ptr halSoundDose; - getHalSoundDose(&halSoundDose); - if (mHalSoundDose == nullptr) { - return false; - } - return true; + return useHalSoundDose(); } -void SoundDoseManager::getHalSoundDose(std::shared_ptr* halSoundDose) const { - std::lock_guard _l(mLock); - *halSoundDose = mHalSoundDose; +bool SoundDoseManager::useHalSoundDose() const { + const std::lock_guard _l(mLock); + return mHalSoundDose.size() > 0; } void SoundDoseManager::resetSoundDose() { diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h index 42a793dc9e..43175f1278 100644 --- a/services/audioflinger/sounddose/SoundDoseManager.h +++ b/services/audioflinger/sounddose/SoundDoseManager.h @@ -94,12 +94,15 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { sp getSoundDoseInterface(const sp& callback); /** - * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr - * for using the internal MEL computation. + * Sets the HAL sound dose interface for a specific module to use for the MEL computation. * * @return true if setting the HAL sound dose value was successful, false otherwise. */ - bool setHalSoundDoseInterface(const std::shared_ptr& halSoundDose); + bool setHalSoundDoseInterface(const std::string &module, + const std::shared_ptr &halSoundDose); + + /** Reset all the stored HAL sound dose interface. */ + void resetHalSoundDoseInterfaces(); /** Returns the cached audio port id from the active devices. */ audio_port_handle_t getIdForAudioDevice( @@ -193,6 +196,7 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override; wp mSoundDoseManager; + std::mutex mCbLock; }; void resetSoundDose(); @@ -206,8 +210,11 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { void setUseFrameworkMel(bool useFrameworkMel); void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices); bool isSoundDoseHalSupported() const; - /** Returns the HAL sound dose interface or null if internal MEL computation is used. */ - void getHalSoundDose(std::shared_ptr* halSoundDose) const; + /** + * Returns true if there is one active HAL sound dose interface or null if internal MEL + * computation is used. + **/ + bool useHalSoundDose() const; mutable std::mutex mLock; @@ -241,7 +248,7 @@ class SoundDoseManager : public audio_utils::MelProcessor::MelCallback { sp mSoundDose GUARDED_BY(mLock); - std::shared_ptr mHalSoundDose GUARDED_BY(mLock); + std::unordered_map> mHalSoundDose GUARDED_BY(mLock); std::shared_ptr mHalSoundDoseCallback GUARDED_BY(mLock); bool mUseFrameworkMel GUARDED_BY(mLock) = false; diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp index 5860d96949..5f6dcb9813 100644 --- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp +++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp @@ -45,6 +45,8 @@ class MelReporterCallback : public IMelReporterCallback { MOCK_METHOD(void, stopMelComputationForDeviceId, (audio_port_handle_t), (override)); }; +constexpr char kPrimaryModule[] = "primary"; +constexpr char kSecondaryModule[] = "secondary"; class SoundDoseManagerTest : public ::testing::Test { protected: @@ -52,17 +54,24 @@ class SoundDoseManagerTest : public ::testing::Test { mMelReporterCallback = sp::make(); mSoundDoseManager = sp::make(mMelReporterCallback); mHalSoundDose = ndk::SharedRefBase::make(); + mSecondaryHalSoundDose = ndk::SharedRefBase::make(); ON_CALL(*mHalSoundDose.get(), setOutputRs2UpperBound) .WillByDefault([] (float rs2) { EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2); return ndk::ScopedAStatus::ok(); }); + ON_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound) + .WillByDefault([] (float rs2) { + EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2); + return ndk::ScopedAStatus::ok(); + }); } sp mMelReporterCallback; sp mSoundDoseManager; std::shared_ptr mHalSoundDose; + std::shared_ptr mSecondaryHalSoundDose; }; TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) { @@ -110,7 +119,7 @@ TEST_F(SoundDoseManagerTest, NewMelValuesCacheNewRecord) { } TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) { - EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr)); + EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, nullptr)); } TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) { @@ -122,7 +131,7 @@ TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) { return ndk::ScopedAStatus::ok(); }); - EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); + EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose)); EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2, /*streamHandle=*/1, @@ -139,8 +148,17 @@ TEST_F(SoundDoseManagerTest, SetHalSoundDoseRegistersHalCallbacks) { EXPECT_NE(nullptr, callback); return ndk::ScopedAStatus::ok(); }); + EXPECT_CALL(*mSecondaryHalSoundDose.get(), setOutputRs2UpperBound).Times(1); + EXPECT_CALL(*mSecondaryHalSoundDose.get(), registerSoundDoseCallback) + .Times(1) + .WillOnce([&] (const std::shared_ptr& callback) { + EXPECT_NE(nullptr, callback); + return ndk::ScopedAStatus::ok(); + }); - EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); + EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose)); + EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kSecondaryModule, + mSecondaryHalSoundDose)); } TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) { @@ -154,7 +172,7 @@ TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgumen return ndk::ScopedAStatus::ok(); }); - EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); + EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose)); EXPECT_NE(nullptr, halCallback); AudioDevice audioDevice = {}; @@ -175,9 +193,9 @@ TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturn return ndk::ScopedAStatus::ok(); }); - EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); + EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose)); EXPECT_NE(nullptr, halCallback); - EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr)); + mSoundDoseManager->resetHalSoundDoseInterfaces(); AudioDevice audioDevice = {}; audioDevice.address.set("test"); @@ -197,7 +215,7 @@ TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) return ndk::ScopedAStatus::ok(); }); - EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose)); + EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(kPrimaryModule, mHalSoundDose)); EXPECT_NE(nullptr, halCallback); AudioDevice audioDevice = {}; From c8bd9270e4cc75ef6a6df45c7d93a1af6448575b Mon Sep 17 00:00:00 2001 From: Brian Lindahl Date: Mon, 28 Aug 2023 09:42:43 -0600 Subject: [PATCH 115/148] Guard render metrics against too-large render times Some apps may rely on SurfaceFlinger heuristics to change large invalid desired render times to 'now' to render video frames as soon as possible. Update render metrics to defensively handle these scenarios by also assuming large invalid desired render times should actually be 'now'. Bug: 294920725 Test: atest DecoderRenderTest#onFrameRendered_whenInvalidRenderTime_indicatesAllFramesRendered_vp9 Change-Id: If50ba1669ba0fdb3c0fbe5b322e12f8b421c9780 --- media/codec2/sfplugin/CCodecBufferChannel.cpp | 9 +++++++++ media/libstagefright/ACodec.cpp | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index feca03dde9..8d70c394fd 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -1042,6 +1042,15 @@ void CCodecBufferChannel::trackReleasedFrame(const IGraphicBufferProducer::Queue if (desiredRenderTimeNs < nowNs) { desiredRenderTimeNs = nowNs; } + + // If the render time is more than a second from now, then pretend the frame is supposed to be + // rendered immediately, because that's what SurfaceFlinger heuristics will do. This is a tight + // coupling, but is really the only way to optimize away unnecessary present fence checks in + // processRenderedFrames. + if (desiredRenderTimeNs > nowNs + 1*1000*1000*1000LL) { + desiredRenderTimeNs = nowNs; + } + // We've just queued a frame to the surface, so keep track of it and later check to see if it is // actually rendered. TrackedFrame frame; diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index d506ee54a8..189de9b200 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -1592,6 +1592,15 @@ void ACodec::trackReleasedFrame(int64_t frameId, int64_t mediaTimeUs, int64_t de if (desiredRenderTimeNs < nowNs) { desiredRenderTimeNs = nowNs; } + + // If the render time is more than a second from now, then pretend the frame is supposed to be + // rendered immediately, because that's what SurfaceFlinger heuristics will do. This is a tight + // coupling, but is really the only way to optimize away unnecessary present fence checks in + // processRenderedFrames. + if (desiredRenderTimeNs > nowNs + 1*1000*1000*1000LL) { + desiredRenderTimeNs = nowNs; + } + // We've just queued a frame to the surface, so keep track of it and later check to see if it is // actually rendered. TrackedFrame frame; From 1ac56eaca3b6bcb459b33a56f9a375b3567074c1 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 27 Jul 2023 15:24:51 -0700 Subject: [PATCH 116/148] ColorConverter: fix handling unspecified range (and one matrix coeff) We default to limited range for matrix selection, but coefficient selection defaulted to full range which resulted in a calculation error and off colors. Also fixed a typo on the 10-bit BT.709 matrix resulting in a slight color shift. Bug: 287750721 Test: POC in bug descriptions Change-Id: I5dcc1a87331ea24ccfcdfbeadd244e2acb464677 --- .../colorconversion/ColorConverter.cpp | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp index f91a8b29c2..6c26c284ad 100644 --- a/media/libstagefright/colorconversion/ColorConverter.cpp +++ b/media/libstagefright/colorconversion/ColorConverter.cpp @@ -363,6 +363,7 @@ struct ColorConverter::Coeffs { int32_t _g_u; int32_t _g_v; int32_t _b_u; + int32_t _c16; // 16 for limited range matrix, 0 for full rance }; /* @@ -425,18 +426,18 @@ namespace { * * clip range 8-bit: [-277, 535], 10-bit: [-1111, 2155] */ -const struct ColorConverter::Coeffs BT601_FULL = { 256, 359, 88, 183, 454 }; -const struct ColorConverter::Coeffs BT601_LIMITED = { 298, 409, 100, 208, 516 }; -const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518 }; +const struct ColorConverter::Coeffs BT601_FULL = { 256, 359, 88, 183, 454, 0 }; +const struct ColorConverter::Coeffs BT601_LIMITED = { 298, 409, 100, 208, 516, 16 }; +const struct ColorConverter::Coeffs BT601_LTD_10BIT = { 299, 410, 101, 209, 518, 16 }; /** * BT.709: K_R = 0.2126; K_B = 0.0722 * * clip range 8-bit: [-289, 547], 10-bit: [-1159, 2202] */ -const struct ColorConverter::Coeffs BT709_FULL = { 256, 403, 48, 120, 475 }; -const struct ColorConverter::Coeffs BT709_LIMITED = { 298, 459, 55, 136, 541 }; -const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 290, 460, 55, 137, 542 }; +const struct ColorConverter::Coeffs BT709_FULL = { 256, 403, 48, 120, 475, 0 }; +const struct ColorConverter::Coeffs BT709_LIMITED = { 298, 459, 55, 136, 541, 16 }; +const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 299, 460, 55, 137, 542, 16 }; /** * BT.2020: K_R = 0.2627; K_B = 0.0593 @@ -445,9 +446,9 @@ const struct ColorConverter::Coeffs BT709_LTD_10BIT = { 290, 460, 55, 137, 542 * * This is the largest clip range. */ -const struct ColorConverter::Coeffs BT2020_FULL = { 256, 377, 42, 146, 482 }; -const struct ColorConverter::Coeffs BT2020_LIMITED = { 298, 430, 48, 167, 548 }; -const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431, 48, 167, 550 }; +const struct ColorConverter::Coeffs BT2020_FULL = { 256, 377, 42, 146, 482, 0 }; +const struct ColorConverter::Coeffs BT2020_LIMITED = { 298, 430, 48, 167, 548, 16 }; +const struct ColorConverter::Coeffs BT2020_LTD_10BIT = { 299, 431, 48, 167, 550, 16 }; constexpr int CLIP_RANGE_MIN_8BIT = -294; constexpr int CLIP_RANGE_MAX_8BIT = 552; @@ -781,7 +782,7 @@ status_t ColorConverter::convertCbYCrY( signed _neg_g_v = -matrix->_g_v; signed _r_v = matrix->_r_v; signed _y = matrix->_y; - signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0; + signed _c16 = matrix->_c16; uint8_t *kAdjustedClip = initClip(); @@ -1257,6 +1258,7 @@ status_t ColorConverter::convertYUVMediaImage( signed _neg_g_v = -matrix->_g_v; signed _r_v = matrix->_r_v; signed _y = matrix->_y; + signed _c16 = matrix->_c16; uint8_t *dst_ptr = (uint8_t *)dst.mBits + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp; @@ -1275,13 +1277,12 @@ status_t ColorConverter::convertYUVMediaImage( //TODO: optimize for chroma sampling, reading and writing multiple pixels // within the same loop - signed _c16 = 0; + void *kAdjustedClip = nullptr; if (mSrcImage->getBitDepth() != ImageBitDepth8) { ALOGE("BitDepth != 8 for MediaImage2"); return ERROR_UNSUPPORTED; } - _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0; kAdjustedClip = initClip(); auto writeToDst = getWriteToDst(mDstFormat, (void *)kAdjustedClip); @@ -1388,7 +1389,7 @@ status_t ColorConverter::convertYUV420Planar16( signed _neg_g_v = -matrix->_g_v; signed _r_v = matrix->_r_v; signed _y = matrix->_y; - signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 16 : 0; + signed _c16 = matrix->_c16; uint8_t *kAdjustedClip = initClip(); @@ -1463,7 +1464,7 @@ status_t ColorConverter::convertYUVP010ToRGBA1010102( signed _neg_g_v = -matrix->_g_v; signed _r_v = matrix->_r_v; signed _y = matrix->_y; - signed _c16 = mSrcColorSpace.mRange == ColorUtils::kColorRangeLimited ? 64 : 0; + signed _c64 = matrix->_c16 * 4; uint16_t *kAdjustedClip10bit = initClip10Bit(); @@ -1483,8 +1484,8 @@ status_t ColorConverter::convertYUVP010ToRGBA1010102( for (size_t y = 0; y < src.cropHeight(); ++y) { for (size_t x = 0; x < src.cropWidth(); x += 2) { signed y1, y2, u, v; - y1 = (src_y[x] >> 6) - _c16; - y2 = (src_y[x + 1] >> 6) - _c16; + y1 = (src_y[x] >> 6) - _c64; + y2 = (src_y[x + 1] >> 6) - _c64; u = int(src_uv[x] >> 6) - 512; v = int(src_uv[x + 1] >> 6) - 512; From 622e3bd6863ebba5b77ef82dea84eb6a3f73491a Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Fri, 25 Aug 2023 22:48:23 +0000 Subject: [PATCH 117/148] Camera: Improve docs for session parameters We mainly cover aeTargetFpsRange and videoStabilizationMode. Test: Read docs Bug: 294619809 Change-Id: I6a8344603f2168cbd77851c2b94afe99cc654bc1 --- camera/ndk/include/camera/NdkCameraMetadataTags.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h index af00e55e4c..4a589bc2d8 100644 --- a/camera/ndk/include/camera/NdkCameraMetadataTags.h +++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h @@ -584,6 +584,13 @@ typedef enum acamera_metadata_tag { *

Only constrains auto-exposure (AE) algorithm, not * manual control of ACAMERA_SENSOR_EXPOSURE_TIME and * ACAMERA_SENSOR_FRAME_DURATION.

+ *

To start a CaptureSession with a target FPS range different from the + * capture request template's default value, the application + * is strongly recommended to call + * {@link ACameraDevice_createCaptureSessionWithSessionParameters } + * with the target fps range before creating the capture session. The aeTargetFpsRange is + * typically a session parameter. Specifying it at session creation time helps avoid + * session reconfiguration delays in cases like 60fps or high speed recording.

* * @see ACAMERA_SENSOR_EXPOSURE_TIME * @see ACAMERA_SENSOR_FRAME_DURATION @@ -1128,6 +1135,12 @@ typedef enum acamera_metadata_tag { * ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE field will return * OFF if the recording output is not stabilized, or if there are no output * Surface types that can be stabilized.

+ *

The application is strongly recommended to call + * {@link ACameraDevice_createCaptureSessionWithSessionParameters } + * with the desired video stabilization mode before creating the capture session. + * Video stabilization mode is a session parameter on many devices. Specifying + * it at session creation time helps avoid reconfiguration delay caused by difference + * between the default value and the first CaptureRequest.

*

If a camera device supports both this mode and OIS * (ACAMERA_LENS_OPTICAL_STABILIZATION_MODE), turning both modes on may * produce undesirable interaction, so it is recommended not to enable From 5300db670249f1663c6fa90e11c1f9e0a043d4fb Mon Sep 17 00:00:00 2001 From: Oscar Azucena Date: Wed, 30 Aug 2023 18:45:18 -0700 Subject: [PATCH 118/148] Add check to prevent recursive calls to compute the same volume Added check to prevent unbounded recursive calls to compute music volume in cases where changing a volume group would lead to recomputation of the music volume. Also added a similar check for ringer and accessibility. In both cases the goal is to prevent recomputing the same volume group. Bug: 293643676 Bug: 298282137 Test: Tested target with notification and music in the same volume group. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:437ded5017947e64dd905444fced0b0b83514034) Merged-In: I40cea1e7c7a5158b309b4e1a440ae88b238b0566 Change-Id: I40cea1e7c7a5158b309b4e1a440ae88b238b0566 --- .../managerdefault/AudioPolicyManager.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 8717083c3e..b3c68b58d3 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -7656,8 +7656,10 @@ float AudioPolicyManager::computeVolume(IVolumeCurves &curves, const auto musicVolumeSrc = toVolumeSource(AUDIO_STREAM_MUSIC, false); const auto alarmVolumeSrc = toVolumeSource(AUDIO_STREAM_ALARM, false); const auto a11yVolumeSrc = toVolumeSource(AUDIO_STREAM_ACCESSIBILITY, false); - - if (volumeSource == a11yVolumeSrc + // Verify that the current volume source is not the ringer volume to prevent recursively + // calling to compute volume. This could happen in cases where a11y and ringer sounds belong + // to the same volume group. + if (volumeSource != ringVolumeSrc && volumeSource == a11yVolumeSrc && (AUDIO_MODE_RINGTONE == mEngine->getPhoneState()) && mOutputs.isActive(ringVolumeSrc, 0)) { auto &ringCurves = getVolumeCurves(AUDIO_STREAM_RING); @@ -7720,8 +7722,12 @@ float AudioPolicyManager::computeVolume(IVolumeCurves &curves, // when the phone is ringing we must consider that music could have been paused just before // by the music application and behave as if music was active if the last music track was // just stopped - if (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) || - mLimitRingtoneVolume) { + // Verify that the current volume source is not the music volume to prevent recursively + // calling to compute volume. This could happen in cases where music and + // (alarm, ring, notification, system, etc.) sounds belong to the same volume group. + if (volumeSource != musicVolumeSrc && + (isStreamActive(AUDIO_STREAM_MUSIC, SONIFICATION_HEADSET_MUSIC_DELAY) + || mLimitRingtoneVolume)) { volumeDb += SONIFICATION_HEADSET_VOLUME_FACTOR_DB; DeviceTypeSet musicDevice = mEngine->getOutputDevicesForAttributes(attributes_initializer(AUDIO_USAGE_MEDIA), From 326166eb164db1764b7f34b2f0cb38bb8ac96e76 Mon Sep 17 00:00:00 2001 From: Arun Johnson Date: Fri, 28 Jul 2023 19:11:52 +0000 Subject: [PATCH 119/148] prepareInitialInputBuffer : retry buffers During flush, if all input buffers are still with component, We retry to get buffers to proceed. Bug: 291241758 Bug: 296988490 Test: atest android.media.decoder.cts.AdaptivePlaybackTest Test: atest android.media.cts.MediaCodecTest Test: atest android.mediav2.cts.CodecDecoderTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ef235a9a63e1b20f7de24d900db5e834f24e1ddb) Merged-In: I6326c4c8542844cf7edb4c22054cc16a596c0af2 Change-Id: I6326c4c8542844cf7edb4c22054cc16a596c0af2 --- media/codec2/sfplugin/CCodec.cpp | 3 +- media/codec2/sfplugin/CCodecBufferChannel.cpp | 31 +++++++++++++------ media/codec2/sfplugin/CCodecBufferChannel.h | 3 +- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp index a75ce70367..1153fb67e1 100644 --- a/media/codec2/sfplugin/CCodec.cpp +++ b/media/codec2/sfplugin/CCodec.cpp @@ -2137,7 +2137,7 @@ void CCodec::signalResume() { } std::map> clientInputBuffers; - status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers); + status_t err = mChannel->prepareInitialInputBuffers(&clientInputBuffers, true); if (err != OK) { if (err == NO_MEMORY) { // NO_MEMORY happens here when all the buffers are still @@ -2160,7 +2160,6 @@ void CCodec::signalResume() { const std::unique_ptr &config = *configLocked; return config->mBuffersBoundToCodec; }()); - { Mutexed::Locked state(mState); if (state->get() != RESUMING) { diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp index feca03dde9..08244bce73 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.cpp +++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -1614,22 +1616,31 @@ status_t CCodecBufferChannel::start( } status_t CCodecBufferChannel::prepareInitialInputBuffers( - std::map> *clientInputBuffers) { + std::map> *clientInputBuffers, bool retry) { if (mInputSurface) { return OK; } size_t numInputSlots = mInput.lock()->numSlots; - - { - Mutexed::Locked input(mInput); - while (clientInputBuffers->size() < numInputSlots) { - size_t index; - sp buffer; - if (!input->buffers->requestNewBuffer(&index, &buffer)) { - break; + int retryCount = 1; + for (; clientInputBuffers->empty() && retryCount >= 0; retryCount--) { + { + Mutexed::Locked input(mInput); + while (clientInputBuffers->size() < numInputSlots) { + size_t index; + sp buffer; + if (!input->buffers->requestNewBuffer(&index, &buffer)) { + break; + } + clientInputBuffers->emplace(index, buffer); } - clientInputBuffers->emplace(index, buffer); + } + if (!retry || (retryCount <= 0)) { + break; + } + if (clientInputBuffers->empty()) { + // wait: buffer may be in transit from component. + std::this_thread::sleep_for(std::chrono::milliseconds(4)); } } if (clientInputBuffers->empty()) { diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h index 41f5ae2e10..f60b6fa121 100644 --- a/media/codec2/sfplugin/CCodecBufferChannel.h +++ b/media/codec2/sfplugin/CCodecBufferChannel.h @@ -140,7 +140,8 @@ class CCodecBufferChannel * initial input buffers. */ status_t prepareInitialInputBuffers( - std::map> *clientInputBuffers); + std::map> *clientInputBuffers, + bool retry = false); /** * Request initial input buffers as prepared in clientInputBuffers. From 3b6930928797892b0da21c43dfd8e9e670a73c21 Mon Sep 17 00:00:00 2001 From: Harish Mahendrakar Date: Thu, 24 Aug 2023 18:20:59 -0700 Subject: [PATCH 120/148] codec2 vts: Fix handling of codec config flag in decoders Only codec config flag from the *.info file needs to be sent to the codecs. Rest of the flags (like sync frame, non display frame) etc are used in the tests and shouldn't be signalled to the codec. Bug: 294262074 Test: atest VtsHalMediaC2V1_0TargetVideoDecTest \ VtsHalMediaC2V1_0TargetAudioDecTest (cherry picked from https://android-review.googlesource.com/q/commit:87cb9127233b71b7eafef7086905056756406cbd) Merged-In: Ic54d20825f2883c4903e6d96ea9c82f738c5e6ea Change-Id: Ic54d20825f2883c4903e6d96ea9c82f738c5e6ea --- .../functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp | 2 +- .../hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h | 2 ++ .../functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp index d47ef6734c..8b0ea91de6 100644 --- a/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp +++ b/media/codec2/hal/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp @@ -341,7 +341,7 @@ void decodeNFrames(const std::shared_ptr& comp ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout"; } int64_t timestamp = (*Info)[frameID].timestamp; - if ((*Info)[frameID].flags) flags = 1u << ((*Info)[frameID].flags - 1); + flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0; if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1)))) flags |= C2FrameData::FLAG_END_OF_STREAM; diff --git a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h index 2222aafbfc..ecab0cb044 100644 --- a/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h +++ b/media/codec2/hal/hidl/1.0/vts/functional/common/media_c2_hidl_test_common.h @@ -28,6 +28,8 @@ #include #define FLAG_NON_DISPLAY_FRAME (1 << 4) +#define FLAG_CONFIG_DATA (1 << 5) + #define MAX_RETRY 20 #define TIME_OUT 400ms #define MAX_INPUT_BUFFERS 8 diff --git a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp index 117d9ca7a4..386e81b6c0 100644 --- a/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp +++ b/media/codec2/hal/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp @@ -459,7 +459,8 @@ void decodeNFrames(const std::shared_ptr& comp ASSERT_TRUE(false) << "Wait for generating C2Work exceeded timeout"; } int64_t timestamp = (*Info)[frameID].timestamp; - if ((*Info)[frameID].flags) flags = (1 << ((*Info)[frameID].flags - 1)); + + flags = ((*Info)[frameID].flags == FLAG_CONFIG_DATA) ? C2FrameData::FLAG_CODEC_CONFIG : 0; if (signalEOS && ((frameID == (int)Info->size() - 1) || (frameID == (offset + range - 1)))) flags |= C2FrameData::FLAG_END_OF_STREAM; From 3c1d9613ef64e01d2e81c4aa44c90dcd8ca958b9 Mon Sep 17 00:00:00 2001 From: Toni Heidenreich Date: Wed, 6 Sep 2023 12:49:33 +0000 Subject: [PATCH 121/148] httplive: fix use-after-free Implement a mutex to ensure secure multi-threaded access to the KeyedVector in MetaDataBase. Concurrent access by different threads can lead to accessing the wrong memory location due to potential changes in the vector Bug: 298057702 Test: HTTP Live Streaming test (cherry picked from https://partner-android-review.googlesource.com/q/commit:a2dfb31957a9d5358d0219a0eda7dcb5b0fff5fe) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:90fb4ca425444429ada6ce0de1c13d35829bc196) Merged-In: Id35ba181185bc93d9f268309a1514c5a18166e12 Change-Id: I46b05c85d9c39f4ce549efc160c08a0646c9fd0a --- media/libstagefright/foundation/MetaDataBase.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp index 4b439c60fc..bb323855a2 100644 --- a/media/libstagefright/foundation/MetaDataBase.cpp +++ b/media/libstagefright/foundation/MetaDataBase.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include #include #include @@ -78,6 +80,7 @@ struct MetaDataBase::Rect { struct MetaDataBase::MetaDataInternal { + std::mutex mLock; KeyedVector mItems; }; @@ -102,10 +105,12 @@ MetaDataBase::~MetaDataBase() { } void MetaDataBase::clear() { + std::lock_guard guard(mInternalData->mLock); mInternalData->mItems.clear(); } bool MetaDataBase::remove(uint32_t key) { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -252,6 +257,7 @@ bool MetaDataBase::setData( uint32_t key, uint32_t type, const void *data, size_t size) { bool overwrote_existing = true; + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { typed_data item; @@ -269,6 +275,7 @@ bool MetaDataBase::setData( bool MetaDataBase::findData(uint32_t key, uint32_t *type, const void **data, size_t *size) const { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -283,6 +290,7 @@ bool MetaDataBase::findData(uint32_t key, uint32_t *type, } bool MetaDataBase::hasData(uint32_t key) const { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -429,6 +437,7 @@ static void MakeFourCCString(uint32_t x, char *s) { String8 MetaDataBase::toString() const { String8 s; + std::lock_guard guard(mInternalData->mLock); for (int i = mInternalData->mItems.size(); --i >= 0;) { int32_t key = mInternalData->mItems.keyAt(i); char cc[5]; @@ -443,6 +452,7 @@ String8 MetaDataBase::toString() const { } void MetaDataBase::dumpToLog() const { + std::lock_guard guard(mInternalData->mLock); for (int i = mInternalData->mItems.size(); --i >= 0;) { int32_t key = mInternalData->mItems.keyAt(i); char cc[5]; @@ -455,6 +465,7 @@ void MetaDataBase::dumpToLog() const { #ifndef __ANDROID_VNDK__ status_t MetaDataBase::writeToParcel(Parcel &parcel) { status_t ret; + std::lock_guard guard(mInternalData->mLock); size_t numItems = mInternalData->mItems.size(); ret = parcel.writeUint32(uint32_t(numItems)); if (ret) { From d0b32f2636ec9d352e4dca6f61375161124607bc Mon Sep 17 00:00:00 2001 From: malikakash Date: Wed, 23 Aug 2023 21:40:40 +0000 Subject: [PATCH 122/148] Implement CameraIdRemapping for API1 - For API1, there's already two Ids: API1CameraId and a HAL camera Id, and they might be different. We only remap the HAL Camera Id, and leave the API1 camera ID untouched (since that is what the app sees). In that sense, there was already a "remapping" from app_camera_id to hal_camera_id in API_1, we just remap that hal_camera_id to different hal_camera_id_2. In addition: - Prevent remapping cameras for system/vendor uids. - Properly implement disconnect() for API1 & API2 clients. This includes: - Clearing binder identity before we call disconnect(), so that the PID checks in disconnect() impl pass. - Not holding the mCameraIdRemappingLock while calling disconnect(), since it can leads to a deadlock, given a call path of disconnect -> finishCameraOps -> updateStatus, which also requires mCameraIdRemappingLock. - Previously, disconnect() for API_2 clients was likely being triggered through a side channel, (e.g. impl in CameraDeviceClient after being sent an ERROR_CAMERA_DEVICE), which didn't happen for API_1 clients Bug: 286287541 Test: Manually tested E2E for API1 and API2 apps. Change-Id: I3985a3ddfb0ea1e012b078089dd76133a7b1b7e9 Merged-In: I82b92e2c94209475f0da0b48c2993ff3b0ac7f28 Merged-In: I1e166e59e9441d8c7fe030320127abcfb373e428 --- .../camera/libcameraservice/CameraService.cpp | 102 +++++++++++------- .../camera/libcameraservice/CameraService.h | 12 +-- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 9f52ddf20b..0f7880aa48 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -817,10 +817,9 @@ void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) std::unique_ptr serviceLockWrapper = AutoConditionLock::waitAndAcquire(mServiceLockWrapper); - Mutex::Autolock lock(mCameraIdRemappingLock); - // This will disconnect all existing clients for camera Ids that are being - // remapped in cameraIdRemapping, but only if they were being used by an - // affected packageName. + // Collect all existing clients for camera Ids that are being + // remapped in the new cameraIdRemapping, but only if they were being used by a + // targeted packageName. std::vector> clientsToDisconnect; std::vector cameraIdsToUpdate; for (const auto& [packageName, injectionMap] : cameraIdRemapping) { @@ -831,7 +830,8 @@ void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) if (clientDescriptor != nullptr) { sp clientSp = clientDescriptor->getValue(); if (clientSp->getPackageName() == packageName) { - // This camera ID is being used by the affected packageName. + // This camera is being used by a targeted packageName and + // being remapped to a new camera Id. We should disconnect it. clientsToDisconnect.push_back(clientSp); cameraIdsToUpdate.push_back(id0); } @@ -839,25 +839,40 @@ void CameraService::remapCameraIds(const TCameraIdRemapping& cameraIdRemapping) } } - // Update mCameraIdRemapping. - mCameraIdRemapping.clear(); - mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end()); + for (auto& clientSp : clientsToDisconnect) { + // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect + // automatically. Note that this itself can cause clientSp->disconnect() based on the + // app's response. + clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE, + CaptureResultExtras{}); + } // Do not hold mServiceLock while disconnecting clients, but retain the condition // blocking other clients from connecting in mServiceLockWrapper if held. mServiceLock.unlock(); + // Clear calling identity for disconnect() PID checks. + int64_t token = CameraThreadState::clearCallingIdentity(); + // Disconnect clients. for (auto& clientSp : clientsToDisconnect) { - // We send up ERROR_CAMERA_DEVICE so that the app attempts to reconnect - // automatically. - clientSp->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE, - CaptureResultExtras{}); - // This also triggers the status updates + // This also triggers a call to updateStatus() which also reads mCameraIdRemapping + // and requires mCameraIdRemappingLock. clientSp->disconnect(); } + // Invoke destructors (which call disconnect()) now while we don't hold the mServiceLock. + clientsToDisconnect.clear(); + + CameraThreadState::restoreCallingIdentity(token); mServiceLock.lock(); + + { + Mutex::Autolock lock(mCameraIdRemappingLock); + // Update mCameraIdRemapping. + mCameraIdRemapping.clear(); + mCameraIdRemapping.insert(cameraIdRemapping.begin(), cameraIdRemapping.end()); + } } std::vector CameraService::findOriginalIdsForRemappedCameraId( @@ -876,28 +891,27 @@ std::vector CameraService::findOriginalIdsForRemappedCameraId( return cameraIds; } -String8 CameraService::resolveCameraId(const String8& inputCameraId) { - return resolveCameraId(inputCameraId, String16("")); -} - String8 CameraService::resolveCameraId( const String8& inputCameraId, + int clientUid, const String16& packageName) { String16 packageNameVal = packageName; if (packageName == String16("")) { - int clientUid = CameraThreadState::getCallingUid(); packageNameVal = getPackageNameFromUid(clientUid); } + if (clientUid < AID_APP_START || packageNameVal == String16("")) { + // We shouldn't remap cameras for processes with system/vendor UIDs. + return inputCameraId; + } Mutex::Autolock lock(mCameraIdRemappingLock); if (auto packageMapIter = mCameraIdRemapping.find(packageNameVal); packageMapIter != mCameraIdRemapping.end()) { - ALOGI("%s: resolveCameraId: packageName found %s", - __FUNCTION__, String8(packageNameVal).c_str()); auto packageMap = packageMapIter->second; if (auto replacementIdIter = packageMap.find(inputCameraId); replacementIdIter != packageMap.end()) { - ALOGI("%s: resolveCameraId: inputId found %s, replacing with %s", + ALOGI("%s: resolveCameraId: remapping cameraId %s for %s to %s", __FUNCTION__, inputCameraId.c_str(), + String8(packageNameVal).c_str(), replacementIdIter->second.c_str()); return replacementIdIter->second; } @@ -909,7 +923,12 @@ Status CameraService::getCameraInfo(int cameraId, bool overrideToPortrait, CameraInfo* cameraInfo) { ATRACE_CALL(); Mutex::Autolock l(mServiceLock); - std::string cameraIdStr = cameraIdIntToStrLocked(cameraId); + + std::string unresolvedCameraId = cameraIdIntToStrLocked(cameraId); + std::string cameraIdStr = resolveCameraId( + String8(unresolvedCameraId.c_str()), + CameraThreadState::getCallingUid()).string(); + if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) { return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera" "characteristics for system only device %s: ", cameraIdStr.c_str()); @@ -978,7 +997,8 @@ String8 CameraService::cameraIdIntToStr(int cameraIdInt) { Status CameraService::getCameraCharacteristics(const String16& unresolvedCameraId, int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) { ATRACE_CALL(); - String8 cameraId = resolveCameraId(String8(unresolvedCameraId)); + String8 cameraId = resolveCameraId(String8(unresolvedCameraId), + CameraThreadState::getCallingUid()); if (!cameraInfo) { ALOGE("%s: cameraInfo is NULL", __FUNCTION__); return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "cameraInfo is NULL"); @@ -1064,9 +1084,11 @@ Status CameraService::getCameraCharacteristics(const String16& unresolvedCameraI return ret; } -Status CameraService::getTorchStrengthLevel(const String16& cameraId, +Status CameraService::getTorchStrengthLevel(const String16& unresolvedCameraId, int32_t* torchStrength) { ATRACE_CALL(); + String8 cameraId = resolveCameraId(String8(unresolvedCameraId), + CameraThreadState::getCallingUid()); Mutex::Autolock l(mServiceLock); if (!mInitialized) { ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__); @@ -1343,7 +1365,9 @@ Status CameraService::getLegacyParametersLazy(int cameraId, return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Parameters must not be null"); } - String8 id = String8::format("%d", cameraId); + String8 unresolvedCameraId = String8::format("%d", cameraId); + String8 id = resolveCameraId(unresolvedCameraId, + CameraThreadState::getCallingUid()); // Check if we already have parameters { @@ -1855,7 +1879,9 @@ Status CameraService::connect( ATRACE_CALL(); Status ret = Status::ok(); - String8 id = cameraIdIntToStr(api1CameraId); + String8 unresolvedCameraId = cameraIdIntToStr(api1CameraId); + String8 id = resolveCameraId(unresolvedCameraId, CameraThreadState::getCallingUid()); + sp client = nullptr; ret = connectHelper(cameraClient, id, api1CameraId, clientPackageName,/*systemNativeClient*/ false, {}, clientUid, clientPid, API_1, @@ -1950,7 +1976,6 @@ Status CameraService::connectDevice( ATRACE_CALL(); Status ret = Status::ok(); - String8 id = resolveCameraId(String8(unresolvedCameraId), clientPackageName); sp client = nullptr; String16 clientPackageNameAdj = clientPackageName; int callingPid = CameraThreadState::getCallingPid(); @@ -1962,6 +1987,10 @@ Status CameraService::connectDevice( systemNativeClient = true; } + String8 id = resolveCameraId(String8(unresolvedCameraId), + CameraThreadState::getCallingUid(), + clientPackageNameAdj); + if (oomScoreOffset < 0) { String8 msg = String8::format("Cannot increase the priority of a client %s pid %d for " @@ -2453,8 +2482,8 @@ Status CameraService::turnOnTorchWithStrengthLevel(const String16& unresolvedCam "Torch client binder in null."); } - String8 id = resolveCameraId(String8(unresolvedCameraId)); int uid = CameraThreadState::getCallingUid(); + String8 id = resolveCameraId(String8(unresolvedCameraId), uid); if (shouldRejectSystemCameraConnection(id)) { return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to change the strength level" @@ -2584,8 +2613,8 @@ Status CameraService::setTorchMode(const String16& unresolvedCameraId, "Torch client Binder is null"); } - String8 id = resolveCameraId(String8(unresolvedCameraId)); int uid = CameraThreadState::getCallingUid(); + String8 id = resolveCameraId(String8(unresolvedCameraId), uid); if (shouldRejectSystemCameraConnection(id)) { return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode" @@ -3113,16 +3142,8 @@ Status CameraService::supportsCameraApi(const String16& unresolvedCameraId, int /*out*/ bool *isSupported) { ATRACE_CALL(); - String8 resolvedId; - if (apiVersion == API_VERSION_2) { - resolvedId = resolveCameraId(String8(unresolvedCameraId)); - } else { // if (apiVersion == API_VERSION_1) - // We don't support remapping for API 1. - // TODO(b/286287541): Also support remapping for API 1. - resolvedId = String8(unresolvedCameraId); - } - - const String8 id = resolvedId; + const String8 id = resolveCameraId(String8(unresolvedCameraId), + CameraThreadState::getCallingUid()); ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string()); @@ -3186,7 +3207,8 @@ Status CameraService::isHiddenPhysicalCamera(const String16& unresolvedCameraId, /*out*/ bool *isSupported) { ATRACE_CALL(); - const String8 id = resolveCameraId(String8(unresolvedCameraId)); + const String8 id = resolveCameraId(String8(unresolvedCameraId), + CameraThreadState::getCallingUid()); ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string()); *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string()); diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 65b11e7f29..0cbdd11737 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -972,15 +972,13 @@ class CameraService : * * This returns the Camera Id to use in case inputCameraId was remapped to a * different Id for the given packageName. Otherwise, it returns the inputCameraId. - */ - String8 resolveCameraId(const String8& inputCameraId, const String16& packageName); - /** - * Resolve the (potentially remapped) camera Id to use. * - * This returns the Camera Id to use in case inputCameraId was remapped to a - * different Id for the packageName of the client. Otherwise, it returns the inputCameraId. + * If the packageName is not provided, it will be inferred from the clientUid. */ - String8 resolveCameraId(const String8& inputCameraId); + String8 resolveCameraId( + const String8& inputCameraId, + int clientUid, + const String16& packageName = String16("")); /** * Updates the state of mCameraIdRemapping, while disconnecting active clients as necessary. From 2b407e5b83dcc366afbcff44ab5f898ddfe6e956 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Mon, 21 Aug 2023 15:07:24 -0700 Subject: [PATCH 123/148] Camera: Flush all state transitions before reconfigureCamera Pending ACTIVE<->IDLE states transitions may be queued in StatusTracker. It's possible that the camera device has transitioned from IDLE to ACTIVE, but StatusTracker hasn't called notifyStatus(ACTIVE) when reconfigureCamera() is called. Solution is to flush the statusTracker before reconfigureCamera(). Test: Camera CTS, vendor testing Bug: 289974845 Change-Id: I4ceb96b855113cc7e042682df344df6481124997 Merged-In: I4ceb96b855113cc7e042682df344df6481124997 --- .../device3/Camera3Device.cpp | 3 ++ .../device3/StatusTracker.cpp | 48 +++++++++++++++---- .../libcameraservice/device3/StatusTracker.h | 9 ++++ 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 71e49fd21a..f4bfb52b6b 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -2336,6 +2336,9 @@ bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int c // deadlocks (http://b/143513518) nsecs_t maxExpectedDuration = getExpectedInFlightDuration(); + // Make sure status tracker is flushed + mStatusTracker->flushPendingStates(); + Mutex::Autolock l(mLock); if (checkAbandonedStreamsLocked()) { ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!", diff --git a/services/camera/libcameraservice/device3/StatusTracker.cpp b/services/camera/libcameraservice/device3/StatusTracker.cpp index ea1f2c1a2f..3a25877cae 100644 --- a/services/camera/libcameraservice/device3/StatusTracker.cpp +++ b/services/camera/libcameraservice/device3/StatusTracker.cpp @@ -34,7 +34,8 @@ StatusTracker::StatusTracker(wp parent) : mParent(parent), mNextComponentId(0), mIdleFence(new Fence()), - mDeviceState(IDLE) { + mDeviceState(IDLE), + mFlushed(true) { } StatusTracker::~StatusTracker() { @@ -111,16 +112,33 @@ void StatusTracker::markComponent(int id, ComponentState state, const sp& componentFence) { ALOGV("%s: Component %d is now %s", __FUNCTION__, id, state == IDLE ? "idle" : "active"); - Mutex::Autolock l(mPendingLock); - StateChange newState = { - id, - state, - componentFence - }; + // If any component state changes, the status tracker is considered + // not flushed. + { + Mutex::Autolock l(mFlushLock); + mFlushed = false; + } - mPendingChangeQueue.add(newState); - mPendingChangeSignal.signal(); + { + Mutex::Autolock l(mPendingLock); + + StateChange newState = { + id, + state, + componentFence + }; + + mPendingChangeQueue.add(newState); + mPendingChangeSignal.signal(); + } +} + +void StatusTracker::flushPendingStates() { + Mutex::Autolock l(mFlushLock); + while (!mFlushed && isRunning()) { + mFlushCondition.waitRelative(mFlushLock, kWaitDuration); + } } void StatusTracker::requestExit() { @@ -128,6 +146,7 @@ void StatusTracker::requestExit() { Thread::requestExit(); // Then exit any waits mPendingChangeSignal.signal(); + mFlushCondition.signal(); } StatusTracker::ComponentState StatusTracker::getDeviceStateLocked() { @@ -227,6 +246,17 @@ bool StatusTracker::threadLoop() { } mStateTransitions.clear(); + // After all pending changes are cleared and notified, mark the tracker + // as flushed. + { + Mutex::Autolock fl(mFlushLock); + Mutex::Autolock pl(mPendingLock); + if (mPendingChangeQueue.size() == 0) { + mFlushed = true; + mFlushCondition.signal(); + } + } + return true; } diff --git a/services/camera/libcameraservice/device3/StatusTracker.h b/services/camera/libcameraservice/device3/StatusTracker.h index 069bff6b65..fc65502f14 100644 --- a/services/camera/libcameraservice/device3/StatusTracker.h +++ b/services/camera/libcameraservice/device3/StatusTracker.h @@ -70,6 +70,10 @@ class StatusTracker: public Thread { void dumpActiveComponents(); + // Flush all pending states inflight in the tracker, and return upon + // completion. + void flushPendingStates(); + virtual void requestExit(); protected: @@ -113,6 +117,11 @@ class StatusTracker: public Thread { // Current overall device state ComponentState mDeviceState; + // For flushing all pending states transitions + bool mFlushed; + Mutex mFlushLock; + Condition mFlushCondition; + // Private to threadLoop // Determine current overall device state From ac6389fb9671e1c43b24db44a63aea689aae0177 Mon Sep 17 00:00:00 2001 From: Vlad Popa Date: Mon, 31 Jul 2023 17:33:25 -0700 Subject: [PATCH 124/148] CSD: enable CSD for BT devices Now that we can categorize the BT devices in setting, we can reenable the CSD calculation. Test: manual Bug: 287011781 Change-Id: I8c5cffb1af5d241a3cba79a05e4fef92ee674be5 --- services/audioflinger/sounddose/SoundDoseManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp index 697d028b30..cb9178b9b2 100644 --- a/services/audioflinger/sounddose/SoundDoseManager.cpp +++ b/services/audioflinger/sounddose/SoundDoseManager.cpp @@ -497,8 +497,7 @@ bool SoundDoseManager::shouldComputeCsdForDeviceType(audio_devices_t device) { switch (device) { case AUDIO_DEVICE_OUT_WIRED_HEADSET: case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: - // TODO(b/278265907): enable A2DP when we can distinguish A2DP headsets - // case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: + case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP: case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES: case AUDIO_DEVICE_OUT_USB_HEADSET: case AUDIO_DEVICE_OUT_BLE_HEADSET: From 0110ff48d6aa76879bfae9283aa43e040da33366 Mon Sep 17 00:00:00 2001 From: David Li Date: Thu, 14 Sep 2023 14:48:47 +0800 Subject: [PATCH 125/148] libaudiohal@aidl: fix the encoder padding and delay ranges Bug: 206737711 Test: mm Test: YTMusic Change-Id: I33f60a4710466c7c28a07fd1ad51a150a3bc69d6 Merged-In: I33f60a4710466c7c28a07fd1ad51a150a3bc69d6 --- media/libaudiohal/impl/StreamHalAidl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp index 80e19a04ae..fe2a18b5be 100644 --- a/media/libaudiohal/impl/StreamHalAidl.cpp +++ b/media/libaudiohal/impl/StreamHalAidl.cpp @@ -836,7 +836,7 @@ status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter ¶me parameters, String8(AudioParameter::keyOffloadCodecDelaySamples), [&](int value) { // The legacy keys are misnamed, the value is in frames. - return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE; + return value >= 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE; }))) { updateMetadata = true; } @@ -844,7 +844,7 @@ status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter ¶me parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples), [&](int value) { // The legacy keys are misnamed, the value is in frames. - return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE; + return value >= 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE; }))) { updateMetadata = true; } From 53b1871bce42d0ba7bd611271eb00eeaf6bffe41 Mon Sep 17 00:00:00 2001 From: Harish Mahendrakar Date: Thu, 7 Sep 2023 19:44:41 +0000 Subject: [PATCH 126/148] C2 VTS: Disable multi-frame tests in audio decoder AAC, AMRWB, AMRNB and MP3 decoders had multi-frame tests, but this is not guaranteed to be supported by all decoders. Also, similar tests were not added for flac, vorbis and opus as those decoders do not support multi-frame input currently. So multi-frame tests are removed for all codecs now. Bug: 294262063 Bug: 299492907 Test: atest VtsHalMediaC2V1_0TargetAudioDecTest Merged-In: I8084b48b4a181e87bd151bc2870eddad36ae3a0b Change-Id: I8084b48b4a181e87bd151bc2870eddad36ae3a0b --- .../codec2/hidl/1.0/vts/functional/Android.bp | 4 - .../VtsHalMediaC2V1_0TargetAudioDecTest.cpp | 8 - .../VtsHalMediaC2V1_0TargetAudioDecTest.xml | 6 +- ...ac_stereo_128kbps_48000hz_multi_frame.info | 443 ---------- ..._amrwb_1ch_14kbps_16000hz_multi_frame.info | 460 ---------- ...p3_stereo_192kbps_48000hz_multi_frame.info | 385 --------- ...e_amrnb_1ch_12kbps_8000hz_multi_frame.info | 807 ------------------ 7 files changed, 1 insertion(+), 2112 deletions(-) delete mode 100644 media/codec2/hidl/1.0/vts/functional/res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info delete mode 100644 media/codec2/hidl/1.0/vts/functional/res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info delete mode 100644 media/codec2/hidl/1.0/vts/functional/res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info delete mode 100644 media/codec2/hidl/1.0/vts/functional/res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info diff --git a/media/codec2/hidl/1.0/vts/functional/Android.bp b/media/codec2/hidl/1.0/vts/functional/Android.bp index 0ae133cd79..1c5c7d6713 100644 --- a/media/codec2/hidl/1.0/vts/functional/Android.bp +++ b/media/codec2/hidl/1.0/vts/functional/Android.bp @@ -29,10 +29,8 @@ filegroup { srcs: [ "res/bbb_aac_stereo_128kbps_48000hz.aac", "res/bbb_aac_stereo_128kbps_48000hz.info", - "res/bbb_aac_stereo_128kbps_48000hz_multi_frame.info", "res/bbb_amrwb_1ch_14kbps_16000hz.amrwb", "res/bbb_amrwb_1ch_14kbps_16000hz.info", - "res/bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info", "res/bbb_flac_stereo_680kbps_48000hz.flac", "res/bbb_flac_stereo_680kbps_48000hz.info", "res/bbb_g711alaw_1ch_8khz.info", @@ -43,7 +41,6 @@ filegroup { "res/bbb_gsm_1ch_8khz_13kbps.raw", "res/bbb_mp3_stereo_192kbps_48000hz.info", "res/bbb_mp3_stereo_192kbps_48000hz.mp3", - "res/bbb_mp3_stereo_192kbps_48000hz_multi_frame.info", "res/bbb_opus_stereo_128kbps_48000hz.info", "res/bbb_opus_stereo_128kbps_48000hz.opus", "res/bbb_raw_1ch_8khz_s32le.info", @@ -52,7 +49,6 @@ filegroup { "res/bbb_vorbis_stereo_128kbps_48000hz.vorbis", "res/sine_amrnb_1ch_12kbps_8000hz.amrnb", "res/sine_amrnb_1ch_12kbps_8000hz.info", - "res/sine_amrnb_1ch_12kbps_8000hz_multi_frame.info", ], } diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp index d47ef6734c..5409b66d96 100644 --- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp +++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp @@ -44,17 +44,9 @@ struct CompToFiles { std::vector gCompToFiles = { {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", "bbb_aac_stereo_128kbps_48000hz.info"}, - {"mp4a-latm", "bbb_aac_stereo_128kbps_48000hz.aac", - "bbb_aac_stereo_128kbps_48000hz_multi_frame.info"}, {"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3", "bbb_mp3_stereo_192kbps_48000hz.info"}, - {"mpeg", "bbb_mp3_stereo_192kbps_48000hz.mp3", - "bbb_mp3_stereo_192kbps_48000hz_multi_frame.info"}, {"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb", "sine_amrnb_1ch_12kbps_8000hz.info"}, - {"3gpp", "sine_amrnb_1ch_12kbps_8000hz.amrnb", - "sine_amrnb_1ch_12kbps_8000hz_multi_frame.info"}, {"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb", "bbb_amrwb_1ch_14kbps_16000hz.info"}, - {"amr-wb", "bbb_amrwb_1ch_14kbps_16000hz.amrwb", - "bbb_amrwb_1ch_14kbps_16000hz_multi_frame.info"}, {"vorbis", "bbb_vorbis_stereo_128kbps_48000hz.vorbis", "bbb_vorbis_stereo_128kbps_48000hz.info"}, {"opus", "bbb_opus_stereo_128kbps_48000hz.opus", "bbb_opus_stereo_128kbps_48000hz.info"}, diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml index a22f8cf132..6c04683eb4 100644 --- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml +++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.xml @@ -23,10 +23,8 @@

Only constrains auto-exposure (AE) algorithm, not * manual control of ACAMERA_SENSOR_EXPOSURE_TIME and * ACAMERA_SENSOR_FRAME_DURATION.

+ *

Note that the actual achievable max framerate also depends on the minimum frame + * duration of the output streams. The max frame rate will be + * min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations). For example, + * if the application sets this key to {60, 60}, but the maximum minFrameDuration among + * all configured streams is 33ms, the maximum framerate won't be 60fps, but will be + * 30fps.

*

To start a CaptureSession with a target FPS range different from the * capture request template's default value, the application * is strongly recommended to call From 300e148b8e80387fa5c9a69feb38f8af53541d19 Mon Sep 17 00:00:00 2001 From: Sohail Nagaraj Date: Thu, 24 Aug 2023 07:39:43 +0000 Subject: [PATCH 146/148] httplive: fix use-after-free Implement a mutex to ensure secure multi-threaded access to the KeyedVector in MetaDataBase. Concurrent access by different threads can lead to accessing the wrong memory location due to potential changes in the vector Bug: 278166920 Test: HTTP Live Streaming test (cherry picked from https://partner-android-review.googlesource.com/q/commit:a2dfb31957a9d5358d0219a0eda7dcb5b0fff5fe) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:90fb4ca425444429ada6ce0de1c13d35829bc196) Merged-In: Id35ba181185bc93d9f268309a1514c5a18166e12 Change-Id: Id35ba181185bc93d9f268309a1514c5a18166e12 --- media/module/foundation/MetaDataBase.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/media/module/foundation/MetaDataBase.cpp b/media/module/foundation/MetaDataBase.cpp index 33707482c9..46a600a9d9 100644 --- a/media/module/foundation/MetaDataBase.cpp +++ b/media/module/foundation/MetaDataBase.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include #include #include @@ -78,6 +80,7 @@ struct MetaDataBase::Rect { struct MetaDataBase::MetaDataInternal { + std::mutex mLock; KeyedVector mItems; }; @@ -102,10 +105,12 @@ MetaDataBase::~MetaDataBase() { } void MetaDataBase::clear() { + std::lock_guard guard(mInternalData->mLock); mInternalData->mItems.clear(); } bool MetaDataBase::remove(uint32_t key) { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -252,6 +257,7 @@ bool MetaDataBase::setData( uint32_t key, uint32_t type, const void *data, size_t size) { bool overwrote_existing = true; + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { typed_data item; @@ -269,6 +275,7 @@ bool MetaDataBase::setData( bool MetaDataBase::findData(uint32_t key, uint32_t *type, const void **data, size_t *size) const { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -283,6 +290,7 @@ bool MetaDataBase::findData(uint32_t key, uint32_t *type, } bool MetaDataBase::hasData(uint32_t key) const { + std::lock_guard guard(mInternalData->mLock); ssize_t i = mInternalData->mItems.indexOfKey(key); if (i < 0) { @@ -429,6 +437,7 @@ static void MakeFourCCString(uint32_t x, char *s) { String8 MetaDataBase::toString() const { String8 s; + std::lock_guard guard(mInternalData->mLock); for (int i = mInternalData->mItems.size(); --i >= 0;) { int32_t key = mInternalData->mItems.keyAt(i); char cc[5]; @@ -443,6 +452,7 @@ String8 MetaDataBase::toString() const { } void MetaDataBase::dumpToLog() const { + std::lock_guard guard(mInternalData->mLock); for (int i = mInternalData->mItems.size(); --i >= 0;) { int32_t key = mInternalData->mItems.keyAt(i); char cc[5]; @@ -455,6 +465,7 @@ void MetaDataBase::dumpToLog() const { #if defined(__ANDROID__) && !defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__) status_t MetaDataBase::writeToParcel(Parcel &parcel) { status_t ret; + std::lock_guard guard(mInternalData->mLock); size_t numItems = mInternalData->mItems.size(); ret = parcel.writeUint32(uint32_t(numItems)); if (ret) { From 95f411fbda480f986811e6f8010f0a2fd91fd206 Mon Sep 17 00:00:00 2001 From: guochuang Date: Fri, 15 Sep 2023 17:45:44 +0800 Subject: [PATCH 147/148] NdkMedia: fix android.mediav2.cts.CodecEncoderSurfaceTest failed. use Abuffer.base instead of data. Bug: 300861053 Test: run cts -m CtsMediaV2TestCases -t android.mediav2.cts.CodecEncoderSurfaceTest Signed-off-by: guochuang (cherry picked from https://android-review.googlesource.com/q/commit:184293b550dec1bcb7b8ba5f2f5342c355f5b4dc) Merged-In: I76ef2c404f8264843973e1af9be1b23fc1e6c3af Change-Id: I76ef2c404f8264843973e1af9be1b23fc1e6c3af --- media/ndk/NdkMediaCodec.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp index af21a99a17..66702a8587 100644 --- a/media/ndk/NdkMediaCodec.cpp +++ b/media/ndk/NdkMediaCodec.cpp @@ -506,7 +506,7 @@ uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_ if (out_size != NULL) { *out_size = abuf->capacity(); } - return abuf->data(); + return abuf->base(); } android::Vector > abufs; @@ -523,7 +523,7 @@ uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_ if (out_size != NULL) { *out_size = abufs[idx]->capacity(); } - return abufs[idx]->data(); + return abufs[idx]->base(); } ALOGE("couldn't get input buffers"); return NULL; @@ -541,7 +541,7 @@ uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out if (out_size != NULL) { *out_size = abuf->capacity(); } - return abuf->data(); + return abuf->base(); } android::Vector > abufs; @@ -554,7 +554,7 @@ uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out if (out_size != NULL) { *out_size = abufs[idx]->capacity(); } - return abufs[idx]->data(); + return abufs[idx]->base(); } ALOGE("couldn't get output buffers"); return NULL; From e75ffb4d68787bba36ea985835e6a51a14393515 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Thu, 19 Oct 2023 18:39:26 +0000 Subject: [PATCH 148/148] Revert "NdkMedia: fix android.mediav2.cts.CodecEncoderSurfaceTest failed." This reverts commit 95f411fbda480f986811e6f8010f0a2fd91fd206. Reason for revert: This breaks app compatibility (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:883e38b694a6a2a51d34ea145607b62b0bdb316f) Merged-In: I94d7034907d5befc0aabf7bf2b490d1fc86c69af Change-Id: I94d7034907d5befc0aabf7bf2b490d1fc86c69af --- media/ndk/NdkMediaCodec.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/media/ndk/NdkMediaCodec.cpp b/media/ndk/NdkMediaCodec.cpp index 2fb5728d2e..b230df5179 100644 --- a/media/ndk/NdkMediaCodec.cpp +++ b/media/ndk/NdkMediaCodec.cpp @@ -672,7 +672,7 @@ uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_ if (out_size != NULL) { *out_size = abuf->capacity(); } - return abuf->base(); + return abuf->data(); } android::Vector > abufs; @@ -689,7 +689,7 @@ uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_ if (out_size != NULL) { *out_size = abufs[idx]->capacity(); } - return abufs[idx]->base(); + return abufs[idx]->data(); } ALOGE("couldn't get input buffers"); return NULL; @@ -707,7 +707,7 @@ uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out if (out_size != NULL) { *out_size = abuf->capacity(); } - return abuf->base(); + return abuf->data(); } android::Vector > abufs; @@ -720,7 +720,7 @@ uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out if (out_size != NULL) { *out_size = abufs[idx]->capacity(); } - return abufs[idx]->base(); + return abufs[idx]->data(); } ALOGE("couldn't get output buffers"); return NULL;