Revert "Implement codec capabilities enforcement." am: 8ee46469bc
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/23674911
Change-Id: Ide09cbf21dbbabc6bfaac357e0ab99ce10050097
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 37f6457..302e250 100644
--- a/Android.bp
+++ b/Android.bp
@@ -102,3 +102,27 @@
},
},
}
+
+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/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1f7083b..62cf827 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -12,3 +12,4 @@
media/libmediatranscoding/
services/mediatranscoding/
media/libaudioclient/tests/
+ media/libaudiohal/tests/
diff --git a/aidl/android/media/audio/IHalAdapterVendorExtension.aidl b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
new file mode 100644
index 0000000..b7a7678
--- /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/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 9783855..2edc0fe 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -749,7 +749,8 @@
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8) ? asString_VP8Profile(pl.mProfile) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC) ? asString_HEVCProfile(pl.mProfile) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9) ? asString_VP9Profile(pl.mProfile) :
- mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1) ? asString_AV1Profile(pl.mProfile) :"??";
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1) ? asString_AV1Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION) ? asString_DolbyVisionProfile(pl.mProfile) :"??";
const char *niceLevel =
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2) ? asString_MPEG2Level(pl.mLevel) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263) ? asString_H263Level(pl.mLevel) :
@@ -759,6 +760,7 @@
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC) ? asString_HEVCTierLevel(pl.mLevel) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9) ? asString_VP9Level(pl.mLevel) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1) ? asString_AV1Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION) ? asString_DolbyVisionLevel(pl.mLevel) :
"??";
list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index d064123..cee44b9 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -126,7 +126,6 @@
static_libs: [
"libmediautils",
"liblog",
- "libdl",
"libdrmframeworkcommon",
"libselinux",
"libstagefright_foundation",
@@ -144,4 +143,4 @@
"android-drm-team@google.com",
],
},
-}
\ No newline at end of file
+}
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 3b06245..4d3f9bd 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -18,6 +18,7 @@
#include <algorithm>
#include <map>
+#include <sstream>
#include <utility>
#include <vector>
@@ -50,6 +51,7 @@
using ::android::status_t;
using ::android::base::unexpected;
+using media::audio::common::AudioAttributes;
using media::audio::common::AudioChannelLayout;
using media::audio::common::AudioConfig;
using media::audio::common::AudioConfigBase;
@@ -62,6 +64,7 @@
using media::audio::common::AudioEncapsulationMetadataType;
using media::audio::common::AudioEncapsulationMode;
using media::audio::common::AudioEncapsulationType;
+using media::audio::common::AudioFlag;
using media::audio::common::AudioFormatDescription;
using media::audio::common::AudioFormatType;
using media::audio::common::AudioGain;
@@ -95,6 +98,20 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Converters
+namespace {
+
+std::vector<std::string> splitString(const std::string& s, char separator) {
+ std::istringstream iss(s);
+ std::string t;
+ std::vector<std::string> result;
+ while (std::getline(iss, t, separator)) {
+ result.push_back(std::move(t));
+ }
+ return result;
+}
+
+} // namespace
+
::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
if (aidl.size() > maxSize - 1) {
return BAD_VALUE;
@@ -262,12 +279,17 @@
DEFINE_INPUT_LAYOUT(MONO),
DEFINE_INPUT_LAYOUT(STEREO),
+ DEFINE_INPUT_LAYOUT(2POINT1),
DEFINE_INPUT_LAYOUT(FRONT_BACK),
+ DEFINE_INPUT_LAYOUT(TRI),
+ DEFINE_INPUT_LAYOUT(3POINT1),
// AUDIO_CHANNEL_IN_6 not supported
DEFINE_INPUT_LAYOUT(2POINT0POINT2),
DEFINE_INPUT_LAYOUT(2POINT1POINT2),
DEFINE_INPUT_LAYOUT(3POINT0POINT2),
DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+ DEFINE_INPUT_LAYOUT(QUAD),
+ DEFINE_INPUT_LAYOUT(PENTA),
DEFINE_INPUT_LAYOUT(5POINT1)
#undef DEFINE_INPUT_LAYOUT
};
@@ -1799,6 +1821,156 @@
return unexpected(BAD_VALUE);
}
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(AudioFlag aidl) {
+ switch (aidl) {
+ case AudioFlag::NONE:
+ return AUDIO_FLAG_NONE;
+ case AudioFlag::AUDIBILITY_ENFORCED:
+ return AUDIO_FLAG_AUDIBILITY_ENFORCED;
+ // The is no AudioFlag::SECURE, see the comment in the AudioFlag.aidl
+ // return AUDIO_FLAG_SECURE;
+ case AudioFlag::SCO:
+ return AUDIO_FLAG_SCO;
+ case AudioFlag::BEACON:
+ return AUDIO_FLAG_BEACON;
+ case AudioFlag::HW_AV_SYNC:
+ return AUDIO_FLAG_HW_AV_SYNC;
+ case AudioFlag::HW_HOTWORD:
+ return AUDIO_FLAG_HW_HOTWORD;
+ case AudioFlag::BYPASS_INTERRUPTION_POLICY:
+ return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
+ case AudioFlag::BYPASS_MUTE:
+ return AUDIO_FLAG_BYPASS_MUTE;
+ case AudioFlag::LOW_LATENCY:
+ return AUDIO_FLAG_LOW_LATENCY;
+ case AudioFlag::DEEP_BUFFER:
+ return AUDIO_FLAG_DEEP_BUFFER;
+ case AudioFlag::NO_MEDIA_PROJECTION:
+ return AUDIO_FLAG_NO_MEDIA_PROJECTION;
+ case AudioFlag::MUTE_HAPTIC:
+ return AUDIO_FLAG_MUTE_HAPTIC;
+ case AudioFlag::NO_SYSTEM_CAPTURE:
+ return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+ case AudioFlag::CAPTURE_PRIVATE:
+ return AUDIO_FLAG_CAPTURE_PRIVATE;
+ case AudioFlag::CONTENT_SPATIALIZED:
+ return AUDIO_FLAG_CONTENT_SPATIALIZED;
+ case AudioFlag::NEVER_SPATIALIZE:
+ return AUDIO_FLAG_NEVER_SPATIALIZE;
+ case AudioFlag::CALL_REDIRECTION:
+ return AUDIO_FLAG_CALL_REDIRECTION;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
+ switch (legacy) {
+ case AUDIO_FLAG_NONE:
+ return AudioFlag::NONE;
+ case AUDIO_FLAG_AUDIBILITY_ENFORCED:
+ return AudioFlag::AUDIBILITY_ENFORCED;
+ case AUDIO_FLAG_SECURE:
+ return unexpected(BAD_VALUE);
+ case AUDIO_FLAG_SCO:
+ return AudioFlag::SCO;
+ case AUDIO_FLAG_BEACON:
+ return AudioFlag::BEACON;
+ case AUDIO_FLAG_HW_AV_SYNC:
+ return AudioFlag::HW_AV_SYNC;
+ case AUDIO_FLAG_HW_HOTWORD:
+ return AudioFlag::HW_HOTWORD;
+ case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
+ return AudioFlag::BYPASS_INTERRUPTION_POLICY;
+ case AUDIO_FLAG_BYPASS_MUTE:
+ return AudioFlag::BYPASS_MUTE;
+ case AUDIO_FLAG_LOW_LATENCY:
+ return AudioFlag::LOW_LATENCY;
+ case AUDIO_FLAG_DEEP_BUFFER:
+ return AudioFlag::DEEP_BUFFER;
+ case AUDIO_FLAG_NO_MEDIA_PROJECTION:
+ return AudioFlag::NO_MEDIA_PROJECTION;
+ case AUDIO_FLAG_MUTE_HAPTIC:
+ return AudioFlag::MUTE_HAPTIC;
+ case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
+ return AudioFlag::NO_SYSTEM_CAPTURE;
+ case AUDIO_FLAG_CAPTURE_PRIVATE:
+ return AudioFlag::CAPTURE_PRIVATE;
+ case AUDIO_FLAG_CONTENT_SPATIALIZED:
+ return AudioFlag::CONTENT_SPATIALIZED;
+ case AUDIO_FLAG_NEVER_SPATIALIZE:
+ return AudioFlag::NEVER_SPATIALIZE;
+ case AUDIO_FLAG_CALL_REDIRECTION:
+ return AudioFlag::CALL_REDIRECTION;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
+ return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, AudioFlag>(
+ aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_bitmask<AudioFlag>,
+ enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
+ return convertBitmask<int32_t, audio_flags_mask_t, AudioFlag, audio_flags_mask_t>(
+ legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
+ indexToEnum_bitmask<audio_flags_mask_t>,
+ enumToMask_bitmask<int32_t, AudioFlag>);
+}
+
+ConversionResult<std::string>
+aidl2legacy_AudioTags_string(const std::vector<std::string>& aidl) {
+ std::ostringstream tagsBuffer;
+ bool hasValue = false;
+ for (const auto& tag : aidl) {
+ if (hasValue) {
+ tagsBuffer << AUDIO_ATTRIBUTES_TAGS_SEPARATOR;
+ }
+ if (strchr(tag.c_str(), AUDIO_ATTRIBUTES_TAGS_SEPARATOR) == nullptr) {
+ tagsBuffer << tag;
+ hasValue = true;
+ } else {
+ ALOGE("Tag is ill-formed: \"%s\"", tag.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ }
+ return tagsBuffer.str();
+}
+
+ConversionResult<std::vector<std::string>>
+legacy2aidl_string_AudioTags(const std::string& legacy) {
+ return splitString(legacy, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+}
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributes_audio_attributes_t(const AudioAttributes& aidl) {
+ audio_attributes_t legacy;
+ legacy.content_type = VALUE_OR_RETURN(
+ aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
+ legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+ legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
+ legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
+ auto tagsString = VALUE_OR_RETURN(aidl2legacy_AudioTags_string(aidl.tags));
+ RETURN_IF_ERROR(aidl2legacy_string(tagsString, legacy.tags, sizeof(legacy.tags)));
+ return legacy;
+}
+
+ConversionResult<AudioAttributes>
+legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy) {
+ AudioAttributes aidl;
+ aidl.contentType = VALUE_OR_RETURN(
+ legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
+ aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+ aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source));
+ aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
+ auto tagsString = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
+ aidl.tags = VALUE_OR_RETURN(legacy2aidl_string_AudioTags(tagsString));
+ return aidl;
+}
ConversionResult<audio_encapsulation_mode_t>
aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
index c64a074..ecd2e5e 100644
--- a/media/audioaidlconversion/AidlConversionNdkCpp.cpp
+++ b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
@@ -15,6 +15,7 @@
*/
#include <algorithm>
+#include <regex>
#include <type_traits>
#define LOG_TAG "AidlConversionNdkCpp"
@@ -34,6 +35,24 @@
namespace {
+bool isVendorExtension(const std::string& s) {
+ // Per definition in AudioAttributes.aidl and {Playback|Record}TrackMetadata.aidl
+ static const std::regex vendorExtension("VX_[A-Z0-9]{3,}_[_A-Z0-9]+");
+ return std::regex_match(s.begin(), s.end(), vendorExtension);
+}
+
+inline bool isNotVendorExtension(const std::string& s) { return !isVendorExtension(s); }
+
+void filterOutNonVendorTagsInPlace(std::vector<std::string>& tags) {
+ if (std::find_if(tags.begin(), tags.end(), isNotVendorExtension) == tags.end()) {
+ return;
+ }
+ std::vector<std::string> temp;
+ temp.reserve(tags.size());
+ std::copy_if(tags.begin(), tags.end(), std::back_inserter(temp), isVendorExtension);
+ tags = std::move(temp);
+}
+
// cpp2ndk and ndk2cpp are universal converters which work for any type,
// however they are not the most efficient way to convert due to extra
// marshaling / unmarshaling step.
@@ -99,12 +118,15 @@
} // namespace
-#define GENERATE_CONVERTERS(packageName, className) \
- ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+#define GENERATE_CONVERTERS(packageName, className) \
+ GENERATE_CONVERTERS_IMPL(packageName, _, className)
+
+#define GENERATE_CONVERTERS_IMPL(packageName, prefix, className) \
+ ConversionResult<::aidl::packageName::className> cpp2ndk##prefix##className( \
const ::packageName::className& cpp) { \
return cpp2ndk<::aidl::packageName::className>(cpp); \
} \
- ConversionResult<::packageName::className> ndk2cpp_##className( \
+ ConversionResult<::packageName::className> ndk2cpp##prefix##className( \
const ::aidl::packageName::className& ndk) { \
return ndk2cpp<::packageName::className>(ndk); \
}
@@ -120,10 +142,46 @@
}
GENERATE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
-GENERATE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+GENERATE_CONVERTERS_IMPL(android::media::audio::common, _Impl_, AudioHalEngineConfig);
GENERATE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMode);
GENERATE_CONVERTERS(android::media::audio::common, AudioPort);
+namespace {
+
+// Filter out all AudioAttributes tags that do not conform to the vendor extension pattern.
+template<typename T>
+void filterOutNonVendorTags(T& audioHalEngineConfig) {
+ for (auto& strategy : audioHalEngineConfig.productStrategies) {
+ for (auto& group : strategy.attributesGroups) {
+ for (auto& attr : group.attributes) {
+ filterOutNonVendorTagsInPlace(attr.tags);
+ }
+ }
+ }
+}
+
+} // namespace
+
+ConversionResult<::aidl::android::media::audio::common::AudioHalEngineConfig>
+cpp2ndk_AudioHalEngineConfig(const ::android::media::audio::common::AudioHalEngineConfig& cpp) {
+ auto conv = cpp2ndk_Impl_AudioHalEngineConfig(cpp);
+ if (conv.ok()) {
+ filterOutNonVendorTags(conv.value());
+ }
+ return conv;
+}
+
+ConversionResult<::android::media::audio::common::AudioHalEngineConfig>
+ndk2cpp_AudioHalEngineConfig(
+ const ::aidl::android::media::audio::common::AudioHalEngineConfig& ndk) {
+ auto conv = ndk2cpp_Impl_AudioHalEngineConfig(ndk);
+ if (conv.ok()) {
+ filterOutNonVendorTags(conv.value());
+ }
+ return conv;
+}
+
+
} // namespace android
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index 903b88a..216bc12 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,6 +1,7 @@
{
"presubmit": [
{
+ "name": "audio_aidl_conversion_tests",
"name": "audio_aidl_ndk_conversion_tests",
"name": "audio_aidl_ndk_cpp_conversion_tests"
}
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index bc9d4d5..7268464 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -37,6 +37,7 @@
#define PREFIX(f) <f>
#endif
+#include PREFIX(android/media/audio/common/AudioAttributes.h)
#include PREFIX(android/media/audio/common/AudioChannelLayout.h)
#include PREFIX(android/media/audio/common/AudioConfig.h)
#include PREFIX(android/media/audio/common/AudioConfigBase.h)
@@ -46,6 +47,7 @@
#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFlag.h)
#include PREFIX(android/media/audio/common/AudioFormatDescription.h)
#include PREFIX(android/media/audio/common/AudioGain.h)
#include PREFIX(android/media/audio/common/AudioGainConfig.h)
@@ -355,6 +357,26 @@
ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
audio_usage_t legacy);
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(media::audio::common::AudioFlag aidl);
+ConversionResult<media::audio::common::AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
+
+ConversionResult<std::string>
+aidl2legacy_AudioTags_string(const std::vector<std::string>& aidl);
+ConversionResult<std::vector<std::string>>
+legacy2aidl_string_AudioTags(const std::string& legacy);
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributes_audio_attributes_t(const media::audio::common::AudioAttributes& aidl);
+ConversionResult<media::audio::common::AudioAttributes>
+legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy);
+
ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
const media::audio::common::AudioUuid &aidl);
ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index f49f681..656d76a 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -119,6 +119,20 @@
}
/**
+ * A generic template that helps convert containers of convertible types without
+ * using an intermediate container.
+ */
+template<typename InputContainer, typename OutputContainer, typename Func>
+::android::status_t convertContainer(const InputContainer& input, OutputContainer* output,
+ const Func& itemConversion) {
+ auto ins = std::inserter(*output, output->begin());
+ for (const auto& item : input) {
+ *ins = VALUE_OR_RETURN_STATUS(itemConversion(item));
+ }
+ return ::android::OK;
+}
+
+/**
* A generic template that helps convert containers of convertible types.
*/
template<typename OutputContainer, typename InputContainer, typename Func>
@@ -208,6 +222,34 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities for handling bitmasks.
+// Some AIDL enums are specified using bit indices, for example:
+// `AidlEnum { FOO = 0, BAR = 1, BAZ = 2' }`
+// while corresponding legacy types universally uses actual bitmasks, for example:
+// `enum legacy_enum_t { LEGACY_FOO = 1 << 0, LEGACY_BAR = 1 << 1, LEGACY_BAZ = 1 << 2 }`
+// There is also the third type used to store the resulting mask, which is combined
+// from individual bits. In AIDL this is typically an int (`int32_t`), in legacy types this
+// is often the enum type itself (although, strictly this is not correct since masks are not
+// declared as part of the enum type). The bit index value always has an integer type.
+//
+// `indexToEnum_index` constructs an instance of the enum from an index,
+// for example `AidlEnum::BAR` from `1`.
+// `indexToEnum_bitmask` produces a corresponding legacy bitmask enum instance,
+// for example, `LEGACY_BAR` (`2`) from `1`.
+// `enumToMask_bitmask` simply casts an enum type to a bitmask type.
+// `enumToMask_index` creates a mask from an enum type which specifies an index.
+//
+// All these functions can be plugged into `convertBitmask`. For example, to implement
+// conversion from `AidlEnum` to `legacy_enum_t`, with a mask stored in `int32_t`,
+// the following call needs to be made:
+// convertBitmask<legacy_enum_t /*DestMask*/, int32_t /*SrcMask*/,
+// legacy_enum_t /*DestEnum*/, AidlEnum /*SrcEnum*/>(
+// maskField /*int32_t*/, aidl2legacy_AidlEnum_legacy_enum_t /*enumConversion*/,
+// indexToEnum_index<AidlEnum> /*srcIndexToEnum*/,
+// enumToMask_bitmask<legacy_enum_t, legacy_enum_t> /*destEnumToMask*/)
+//
+// The only extra function needed is for mapping between corresponding enum values
+// of the AidlEnum and the legacy_enum_t. Note that the mapping is between values
+// of enums, for example, `AidlEnum::BAZ` maps to `LEGACY_BAZ` and vice versa.
template<typename Enum>
Enum indexToEnum_index(int index) {
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
index c505e60..60727b4 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
namespace {
@@ -89,3 +90,48 @@
ASSERT_EQ(1, convBack.value().tags.size());
EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
}
+
+class AudioTagsRoundTripTest : public testing::TestWithParam<std::vector<std::string>>
+{
+};
+TEST_P(AudioTagsRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto& initial = GetParam();
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = legacy2aidl_string_AudioTags(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioTagsRoundTrip, AudioTagsRoundTripTest,
+ testing::Values(std::vector<std::string>{},
+ std::vector<std::string>{"VX_GOOGLE_41"},
+ std::vector<std::string>{"VX_GOOGLE_41", "VX_GOOGLE_42"}));
+
+TEST(AudioTags, NonVendorTagsAllowed) {
+ const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+ const std::vector<std::string> initial{"random_string", "VX_GOOGLE_42"};
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ ASSERT_TRUE(conv.ok());
+ EXPECT_EQ("random_string" + separator + "VX_GOOGLE_42", conv.value());
+}
+
+TEST(AudioTags, IllFormedAidlTag) {
+ const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+ {
+ const std::vector<std::string> initial{"VX_GOOGLE" + separator + "42", "VX_GOOGLE_42"};
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ if (conv.ok()) {
+ EXPECT_EQ("VX_GOOGLE_42", conv.value());
+ }
+ // Failing this conversion is also OK. The result depends on whether the conversion
+ // only passes through vendor tags.
+ }
+ {
+ const std::vector<std::string> initial{
+ "random_string", "random" + separator + "string", "VX_GOOGLE_42"};
+ auto conv = aidl2legacy_AudioTags_string(initial);
+ if (conv.ok()) {
+ EXPECT_EQ("VX_GOOGLE_42", conv.value());
+ }
+ }
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
index 735a14b..206c35b 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
@@ -125,3 +125,12 @@
INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip, AudioFormatDescriptionRoundTripTest,
testing::Values(make_AFD_Invalid(), make_AFD_Default(), make_AFD_Pcm16Bit(),
make_AFD_Bitstream(), make_AFD_Encap(), make_AFD_Encap_with_Enc()));
+
+TEST(AudioPortRoundTripTest, Ndk2Cpp2Ndk) {
+ const AudioPort initial;
+ auto conv = ndk2cpp_AudioPort(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = cpp2ndk_AudioPort(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 182edfb..591d56d 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -188,12 +188,6 @@
return onStop();
}
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
- work->worklets.front()->output.flags = work->input.flags;
- work->worklets.front()->output.buffers.clear();
- work->worklets.front()->output.ordinal = work->input.ordinal;
-}
-
void C2SoftFlacEnc::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
@@ -245,12 +239,10 @@
mWroteHeader = true;
}
- const uint32_t sampleRate = mIntf->getSampleRate();
const uint32_t channelCount = mIntf->getChannelCount();
const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
const unsigned frameSize = channelCount * sampleSize;
- const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
size_t outCapacity = inSize;
outCapacity += mBlockSize * frameSize;
@@ -270,6 +262,33 @@
return;
}
+ class FillWork {
+ public:
+ FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
+ const std::shared_ptr<C2Buffer> &buffer)
+ : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
+ ~FillWork() = default;
+
+ void operator()(const std::unique_ptr<C2Work> &work) {
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
+ work->worklets.front()->output.buffers.clear();
+ work->worklets.front()->output.ordinal = mOrdinal;
+ work->workletsProcessed = 1u;
+ work->result = C2_OK;
+ if (mBuffer) {
+ work->worklets.front()->output.buffers.push_back(mBuffer);
+ }
+ ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
+ mOrdinal.timestamp.peekll(), mOrdinal.frameIndex.peekll(),
+ mBuffer ? "" : "o");
+ }
+
+ private:
+ const uint32_t mFlags;
+ const C2WorkOrdinalStruct mOrdinal;
+ const std::shared_ptr<C2Buffer> mBuffer;
+ };
+
mEncoderWriteData = true;
mEncoderReturnedNbBytes = 0;
size_t inPos = 0;
@@ -308,14 +327,33 @@
mOutputBlock.reset();
return;
}
- fillEmptyWork(work);
- if (mEncoderReturnedNbBytes != 0) {
- std::shared_ptr<C2Buffer> buffer = createLinearBuffer(std::move(mOutputBlock), 0, mEncoderReturnedNbBytes);
- work->worklets.front()->output.buffers.push_back(buffer);
- work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
- } else {
- ALOGV("encoder process_interleaved returned without data to write");
+
+ // cloneAndSend will create clone of work when more than one encoded frame is produced
+ while (mOutputBuffers.size() > 1) {
+ const OutputBuffer& front = mOutputBuffers.front();
+ C2WorkOrdinalStruct ordinal = work->input.ordinal;
+ ordinal.frameIndex = front.frameIndex;
+ ordinal.timestamp = front.timestampUs;
+ cloneAndSend(work->input.ordinal.frameIndex.peeku(), work,
+ FillWork(C2FrameData::FLAG_INCOMPLETE, ordinal, front.buffer));
+ mOutputBuffers.pop_front();
}
+
+ std::shared_ptr<C2Buffer> buffer;
+ C2WorkOrdinalStruct ordinal = work->input.ordinal;
+ if (mOutputBuffers.size() == 1) {
+ const OutputBuffer& front = mOutputBuffers.front();
+ ordinal.frameIndex = front.frameIndex;
+ ordinal.timestamp = front.timestampUs;
+ buffer = front.buffer;
+ mOutputBuffers.pop_front();
+ }
+ // finish the response for the overall transaction.
+ // this includes any final frame that the encoder produced during this request
+ // this response is required even if no data was encoded.
+ FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
+ ordinal, buffer)(work);
+
mOutputBlock = nullptr;
if (eos) {
mSignalledOutputEos = true;
@@ -349,6 +387,8 @@
// write encoded data
C2WriteView wView = mOutputBlock->map().get();
uint8_t* outData = wView.data();
+ const uint32_t sampleRate = mIntf->getSampleRate();
+ const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
ALOGV("writing %zu bytes of encoded data on output", bytes);
// increment mProcessedSamples to maintain audio synchronization during
// play back
@@ -359,7 +399,12 @@
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
memcpy(outData + mEncoderReturnedNbBytes, buffer, bytes);
+
+ std::shared_ptr<C2Buffer> c2Buffer =
+ createLinearBuffer(mOutputBlock, mEncoderReturnedNbBytes, bytes);
+ mOutputBuffers.push_back({c2Buffer, mAnchorTimeStamp + outTimeStamp, current_frame});
mEncoderReturnedNbBytes += bytes;
+
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.h b/media/codec2/components/flac/C2SoftFlacEnc.h
index b3f01d5..a971ab5 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.h
+++ b/media/codec2/components/flac/C2SoftFlacEnc.h
@@ -79,6 +79,12 @@
unsigned mHeaderOffset;
bool mWroteHeader;
char mHeader[FLAC_HEADER_SIZE];
+ struct OutputBuffer {
+ std::shared_ptr<C2Buffer> buffer;
+ c2_cntr64_t timestampUs;
+ std::uint64_t frameIndex;
+ };
+ std::list<OutputBuffer> mOutputBuffers;
C2_DO_NOT_COPY(C2SoftFlacEnc);
};
diff --git a/media/codec2/core/include/C2Buffer.h b/media/codec2/core/include/C2Buffer.h
index abe343b..7e1df91 100644
--- a/media/codec2/core/include/C2Buffer.h
+++ b/media/codec2/core/include/C2Buffer.h
@@ -101,6 +101,8 @@
/**
* Returns a file descriptor that can be used to wait for this fence in a select system call.
+ * \note If there are multiple file descriptors in fence then a file descriptor for merged fence
+ * would be returned
* \note The returned file descriptor, if valid, must be closed by the caller.
*
* This can be used in e.g. poll() system calls. This file becomes readable (POLLIN) when the
@@ -129,6 +131,7 @@
std::shared_ptr<Impl> mImpl;
C2Fence(std::shared_ptr<Impl> impl);
friend struct _C2FenceFactory;
+ friend std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence);
};
/**
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index d72d228..51082d1 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1598,7 +1598,8 @@
watcher->inputDelay(inputDelayValue)
.pipelineDelay(pipelineDelayValue)
.outputDelay(outputDelayValue)
- .smoothnessFactor(kSmoothnessFactor);
+ .smoothnessFactor(kSmoothnessFactor)
+ .tunneled(mTunneled);
watcher->flush();
}
@@ -2007,6 +2008,7 @@
newInputDelay.value_or(input->inputDelay) +
newPipelineDelay.value_or(input->pipelineDelay) +
kSmoothnessFactor;
+ input->inputDelay = newInputDelay.value_or(input->inputDelay);
if (input->buffers->isArrayMode()) {
if (input->numSlots >= newNumSlots) {
input->numExtraSlots = 0;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 82c31a8..228ad7e 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -478,19 +478,56 @@
mInitCheck = NO_INIT;
return;
case C2PlanarLayout::TYPE_RGB:
- ALOGD("Converter: unrecognized color format "
- "(client %d component %d) for RGB layout",
- mClientColorFormat, mComponentColorFormat);
- mInitCheck = NO_INIT;
+ mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
// TODO: support MediaImage layout
- return;
+ switch (mClientColorFormat) {
+ case COLOR_FormatSurface:
+ case COLOR_FormatRGBFlexible:
+ case COLOR_Format24bitBGR888:
+ case COLOR_Format24bitRGB888:
+ ALOGD("Converter: accept color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ break;
+ default:
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGB layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ if (layout.numPlanes != 3) {
+ ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ break;
case C2PlanarLayout::TYPE_RGBA:
- ALOGD("Converter: unrecognized color format "
- "(client %d component %d) for RGBA layout",
- mClientColorFormat, mComponentColorFormat);
- mInitCheck = NO_INIT;
+ mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
// TODO: support MediaImage layout
- return;
+ switch (mClientColorFormat) {
+ case COLOR_FormatSurface:
+ case COLOR_FormatRGBAFlexible:
+ case COLOR_Format32bitABGR8888:
+ case COLOR_Format32bitARGB8888:
+ case COLOR_Format32bitBGRA8888:
+ ALOGD("Converter: accept color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ break;
+ default:
+ ALOGD("Converter: unrecognized color format "
+ "(client %d component %d) for RGBA layout",
+ mClientColorFormat, mComponentColorFormat);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ if (layout.numPlanes != 4) {
+ ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
+ mInitCheck = BAD_VALUE;
+ return;
+ }
+ break;
default:
mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
if (layout.numPlanes == 1) {
diff --git a/media/codec2/sfplugin/PipelineWatcher.cpp b/media/codec2/sfplugin/PipelineWatcher.cpp
index bc9197c..fa70a28 100644
--- a/media/codec2/sfplugin/PipelineWatcher.cpp
+++ b/media/codec2/sfplugin/PipelineWatcher.cpp
@@ -45,6 +45,11 @@
return *this;
}
+PipelineWatcher &PipelineWatcher::tunneled(bool value) {
+ mTunneled = value;
+ return *this;
+}
+
void PipelineWatcher::onWorkQueued(
uint64_t frameIndex,
std::vector<std::shared_ptr<C2Buffer>> &&buffers,
@@ -87,8 +92,13 @@
ALOGV("onWorkDone(frameIndex=%llu)", (unsigned long long)frameIndex);
auto it = mFramesInPipeline.find(frameIndex);
if (it == mFramesInPipeline.end()) {
- ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
- (unsigned long long)frameIndex);
+ if (!mTunneled) {
+ ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
+ (unsigned long long)frameIndex);
+ } else {
+ ALOGV("onWorkDone: frameIndex not found (%llu); ignored",
+ (unsigned long long)frameIndex);
+ }
return;
}
(void)mFramesInPipeline.erase(it);
diff --git a/media/codec2/sfplugin/PipelineWatcher.h b/media/codec2/sfplugin/PipelineWatcher.h
index 1e23147..b29c7cd 100644
--- a/media/codec2/sfplugin/PipelineWatcher.h
+++ b/media/codec2/sfplugin/PipelineWatcher.h
@@ -37,7 +37,8 @@
: mInputDelay(0),
mPipelineDelay(0),
mOutputDelay(0),
- mSmoothnessFactor(0) {}
+ mSmoothnessFactor(0),
+ mTunneled(false) {}
~PipelineWatcher() = default;
/**
@@ -65,6 +66,12 @@
PipelineWatcher &smoothnessFactor(uint32_t value);
/**
+ * \param value the new tunneled value
+ * \return this object
+ */
+ PipelineWatcher &tunneled(bool value);
+
+ /**
* Client queued a work item to the component.
*
* \param frameIndex input frame index of this work
@@ -122,6 +129,7 @@
uint32_t mPipelineDelay;
uint32_t mOutputDelay;
uint32_t mSmoothnessFactor;
+ bool mTunneled;
struct Frame {
Frame(std::vector<std::shared_ptr<C2Buffer>> &&b,
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index aa908a8..0344fd3 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -190,7 +190,6 @@
if (timeoutMs > INT_MAX) {
timeoutMs = INT_MAX;
}
-
switch (mFence->wait((int)timeoutMs)) {
case NO_ERROR:
return C2_OK;
@@ -202,7 +201,7 @@
}
virtual bool valid() const {
- return mFence->getStatus() != Fence::Status::Invalid;
+ return (mFence && (mFence->getStatus() != Fence::Status::Invalid));
}
virtual bool ready() const {
@@ -213,6 +212,14 @@
return mFence->dup();
}
+ std::vector<int> fds() const {
+ std::vector<int> retFds;
+ for (int index = 0; index < mListFences.size(); index++) {
+ retFds.push_back(mListFences[index]->dup());
+ }
+ return retFds;
+ }
+
virtual bool isHW() const {
return true;
}
@@ -222,39 +229,95 @@
}
virtual native_handle_t *createNativeHandle() const {
- native_handle_t* nh = native_handle_create(1, 1);
+ std::vector<int> nativeFds = fds();
+ nativeFds.push_back(fd());
+ native_handle_t* nh = native_handle_create(nativeFds.size(), 1);
if (!nh) {
ALOGE("Failed to allocate native handle for sync fence");
+ for (int fd : nativeFds) {
+ close(fd);
+ }
return nullptr;
}
- nh->data[0] = fd();
- nh->data[1] = type();
+
+ for (int i = 0; i < nativeFds.size(); i++) {
+ nh->data[i] = nativeFds[i];
+ }
+ nh->data[nativeFds.size()] = type();
return nh;
}
virtual ~SyncFenceImpl() {};
SyncFenceImpl(int fenceFd) :
- mFence(sp<Fence>::make(fenceFd)) {}
+ mFence(sp<Fence>::make(fenceFd)) {
+ mListFences.clear();
+ if (mFence) {
+ mListFences.push_back(mFence);
+ }
+ }
+
+ SyncFenceImpl(const std::vector<int>& fenceFds, int mergedFd) {
+ mListFences.clear();
+
+ for (int fenceFd : fenceFds) {
+ if (fenceFd < 0) {
+ continue;
+ } else {
+ mListFences.push_back(sp<Fence>::make(fenceFd));
+ if (!mListFences.back()) {
+ mFence.clear();
+ break;
+ }
+ if (mergedFd == -1) {
+ mFence = (mFence == nullptr) ? (mListFences.back()) :
+ (Fence::merge("syncFence", mFence, mListFences.back()));
+ }
+ }
+ }
+ if (mergedFd != -1)
+ {
+ mFence = sp<Fence>::make(mergedFd);
+ }
+ if (!mFence) {
+ mListFences.clear();
+ }
+ }
static std::shared_ptr<SyncFenceImpl> CreateFromNativeHandle(const native_handle_t* nh) {
- if (!nh || nh->numFds != 1 || nh->numInts != 1) {
+ if (!nh || nh->numFds < 1 || nh->numInts < 1) {
ALOGE("Invalid handle for sync fence");
return nullptr;
}
- int fd = dup(nh->data[0]);
- std::shared_ptr<SyncFenceImpl> p = std::make_shared<SyncFenceImpl>(fd);
+ std::vector<int> fds;
+ for (int i = 0; i < nh->numFds-1; i++) {
+ fds.push_back(dup(nh->data[i]));
+ }
+ std::shared_ptr<SyncFenceImpl> p = (nh->numFds == 1)?
+ (std::make_shared<SyncFenceImpl>(fds.back())):
+ (std::make_shared<SyncFenceImpl>(fds, (dup(nh->data[nh->numFds-1]))));
if (!p) {
ALOGE("Failed to allocate sync fence impl");
- close(fd);
+ for (int fd : fds) {
+ close(fd);
+ }
}
return p;
}
private:
- const sp<Fence> mFence;
+ std::vector<sp<Fence>> mListFences;
+ sp<Fence> mFence; //merged fence in case mListFences size > 0
};
+std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence) {
+ std::vector<int> retFds;
+ if ((fence.mImpl) && (fence.mImpl->type() == C2Fence::Impl::SYNC_FENCE)) {
+ retFds = static_cast<_C2FenceFactory::SyncFenceImpl *>(fence.mImpl.get())->fds();
+ }
+ return retFds;
+}
+
C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd) {
std::shared_ptr<C2Fence::Impl> p;
if (fenceFd >= 0) {
@@ -262,8 +325,7 @@
if (!p) {
ALOGE("Failed to allocate sync fence impl");
close(fenceFd);
- }
- if (!p->valid()) {
+ } else if (!p->valid()) {
p.reset();
}
} else {
@@ -272,6 +334,25 @@
return C2Fence(p);
}
+C2Fence _C2FenceFactory::CreateMultipleFdSyncFence(const std::vector<int>& fenceFds) {
+ std::shared_ptr<C2Fence::Impl> p;
+ if (fenceFds.size() > 0) {
+ p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFds, -1);
+ if (!p) {
+ ALOGE("Failed to allocate sync fence impl closing FDs");
+ for (int fenceFd : fenceFds) {
+ close(fenceFd);
+ }
+ } else if (!p->valid()) {
+ ALOGE("Invalid sync fence created");
+ p.reset();
+ }
+ } else {
+ ALOGE("Create sync fence from invalid fd list of size 0");
+ }
+ return C2Fence(p);
+}
+
native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
}
diff --git a/media/codec2/vndk/include/C2FenceFactory.h b/media/codec2/vndk/include/C2FenceFactory.h
index 4944115..ef25c47 100644
--- a/media/codec2/vndk/include/C2FenceFactory.h
+++ b/media/codec2/vndk/include/C2FenceFactory.h
@@ -20,6 +20,16 @@
#include <C2Buffer.h>
+/*
+ * Create a list of fds from fence
+ *
+ * \param fence C2Fence object from which associated
+ * file descriptors need to be extracted
+ * \return a vector of fds otherwise return vector of size 0
+ */
+
+std::vector<int> ExtractFdsFromCodec2SyncFence(const C2Fence& fence);
+
class C2SurfaceSyncMemory;
/**
@@ -48,6 +58,14 @@
*/
static C2Fence CreateSyncFence(int fenceFd);
+ /*
+ * Create C2Fence from list of fence file fds.
+ *
+ * \param fenceFds Vector of file descriptor for fence.
+ * It will be owned and closed by the returned fence object.
+ */
+ static C2Fence CreateMultipleFdSyncFence(const std::vector<int>& fenceFds);
+
/**
* Create a native handle from fence for marshalling
*
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index b32667e..bd10e44 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -480,129 +480,6 @@
return aidl;
}
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
- switch (aidl) {
- case media::AudioFlag::AUDIBILITY_ENFORCED:
- return AUDIO_FLAG_AUDIBILITY_ENFORCED;
- case media::AudioFlag::SECURE:
- return AUDIO_FLAG_SECURE;
- case media::AudioFlag::SCO:
- return AUDIO_FLAG_SCO;
- case media::AudioFlag::BEACON:
- return AUDIO_FLAG_BEACON;
- case media::AudioFlag::HW_AV_SYNC:
- return AUDIO_FLAG_HW_AV_SYNC;
- case media::AudioFlag::HW_HOTWORD:
- return AUDIO_FLAG_HW_HOTWORD;
- case media::AudioFlag::BYPASS_INTERRUPTION_POLICY:
- return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
- case media::AudioFlag::BYPASS_MUTE:
- return AUDIO_FLAG_BYPASS_MUTE;
- case media::AudioFlag::LOW_LATENCY:
- return AUDIO_FLAG_LOW_LATENCY;
- case media::AudioFlag::DEEP_BUFFER:
- return AUDIO_FLAG_DEEP_BUFFER;
- case media::AudioFlag::NO_MEDIA_PROJECTION:
- return AUDIO_FLAG_NO_MEDIA_PROJECTION;
- case media::AudioFlag::MUTE_HAPTIC:
- return AUDIO_FLAG_MUTE_HAPTIC;
- case media::AudioFlag::NO_SYSTEM_CAPTURE:
- return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
- case media::AudioFlag::CAPTURE_PRIVATE:
- return AUDIO_FLAG_CAPTURE_PRIVATE;
- case media::AudioFlag::CONTENT_SPATIALIZED:
- return AUDIO_FLAG_CONTENT_SPATIALIZED;
- case media::AudioFlag::NEVER_SPATIALIZE:
- return AUDIO_FLAG_NEVER_SPATIALIZE;
- case media::AudioFlag::CALL_REDIRECTION:
- return AUDIO_FLAG_CALL_REDIRECTION;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioFlag>
-legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
- switch (legacy) {
- case AUDIO_FLAG_NONE:
- return unexpected(BAD_VALUE);
- case AUDIO_FLAG_AUDIBILITY_ENFORCED:
- return media::AudioFlag::AUDIBILITY_ENFORCED;
- case AUDIO_FLAG_SECURE:
- return media::AudioFlag::SECURE;
- case AUDIO_FLAG_SCO:
- return media::AudioFlag::SCO;
- case AUDIO_FLAG_BEACON:
- return media::AudioFlag::BEACON;
- case AUDIO_FLAG_HW_AV_SYNC:
- return media::AudioFlag::HW_AV_SYNC;
- case AUDIO_FLAG_HW_HOTWORD:
- return media::AudioFlag::HW_HOTWORD;
- case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
- return media::AudioFlag::BYPASS_INTERRUPTION_POLICY;
- case AUDIO_FLAG_BYPASS_MUTE:
- return media::AudioFlag::BYPASS_MUTE;
- case AUDIO_FLAG_LOW_LATENCY:
- return media::AudioFlag::LOW_LATENCY;
- case AUDIO_FLAG_DEEP_BUFFER:
- return media::AudioFlag::DEEP_BUFFER;
- case AUDIO_FLAG_NO_MEDIA_PROJECTION:
- return media::AudioFlag::NO_MEDIA_PROJECTION;
- case AUDIO_FLAG_MUTE_HAPTIC:
- return media::AudioFlag::MUTE_HAPTIC;
- case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
- return media::AudioFlag::NO_SYSTEM_CAPTURE;
- case AUDIO_FLAG_CAPTURE_PRIVATE:
- return media::AudioFlag::CAPTURE_PRIVATE;
- case AUDIO_FLAG_CONTENT_SPATIALIZED:
- return media::AudioFlag::CONTENT_SPATIALIZED;
- case AUDIO_FLAG_NEVER_SPATIALIZE:
- return media::AudioFlag::NEVER_SPATIALIZE;
- case AUDIO_FLAG_CALL_REDIRECTION:
- return media::AudioFlag::CALL_REDIRECTION;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
- return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, media::AudioFlag>(
- aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_index<media::AudioFlag>,
- enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
- return convertBitmask<int32_t, audio_flags_mask_t, media::AudioFlag, audio_flags_mask_t>(
- legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
- indexToEnum_bitmask<audio_flags_mask_t>,
- enumToMask_index<int32_t, media::AudioFlag>);
-}
-
-ConversionResult<audio_attributes_t>
-aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl) {
- audio_attributes_t legacy;
- legacy.content_type = VALUE_OR_RETURN(
- aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
- legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
- legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
- legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
- RETURN_IF_ERROR(aidl2legacy_string(aidl.tags, legacy.tags, sizeof(legacy.tags)));
- return legacy;
-}
-
-ConversionResult<media::AudioAttributesInternal>
-legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy) {
- media::AudioAttributesInternal aidl;
- aidl.contentType = VALUE_OR_RETURN(
- legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
- aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
- aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source));
- aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
- aidl.tags = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
- return aidl;
-}
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
sp<IMemory> legacy;
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 7122af1..01e3d53 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -281,10 +281,8 @@
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 4527e0f..7cec2e8 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1066,8 +1066,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
AudioConfig configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
@@ -1106,7 +1106,7 @@
*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 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
int32_t inputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(*input));
int32_t riidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_unique_id_t_int32_t(riid));
int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
@@ -1293,8 +1293,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
int32_t indexAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(index));
AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
@@ -1308,8 +1308,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
int32_t indexAidl;
@@ -1323,8 +1323,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
int32_t indexAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->getMaxVolumeIndexForAttributes(attrAidl, &indexAidl)));
@@ -1336,8 +1336,8 @@
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attr));
int32_t indexAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->getMinVolumeIndexForAttributes(attrAidl, &indexAidl)));
@@ -1369,8 +1369,8 @@
const sp<IAudioPolicyService>& 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<AudioDevice> retAidl;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(aps->getDevicesForAttributes(aaAidl, forVolume, &retAidl)));
@@ -1888,8 +1888,8 @@
media::AudioPortConfigFw sourceAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_config_AudioPortConfigFw(*source));
- media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attributes));
+ media::audio::common::AudioAttributes attributesAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attributes));
int32_t portIdAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
aps->startAudioSource(sourceAidl, attributesAidl, &portIdAidl)));
@@ -2175,8 +2175,8 @@
const sp<IAudioPolicyService>& 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 @@
const sp<IAudioPolicyService>& 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 @@
audio_attributes_t attributes = attr != nullptr ? *attr : AUDIO_ATTRIBUTES_INITIALIZER;
audio_config_t configuration = config != nullptr ? *config : AUDIO_CONFIG_INITIALIZER;
- std::optional<media::AudioAttributesInternal> attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
+ std::optional<media::audio::common::AudioAttributes> attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
std::optional<AudioConfig> configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(configuration, false /*isInput*/));
std::vector<AudioDevice> devicesAidl = VALUE_OR_RETURN_STATUS(
@@ -2449,8 +2449,8 @@
return PERMISSION_DENIED;
}
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
AudioConfig configAidl = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
@@ -2473,8 +2473,8 @@
return PERMISSION_DENIED;
}
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
std::vector<media::audio::common::AudioProfile> audioProfilesAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2653,8 +2653,8 @@
return PERMISSION_DENIED;
}
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
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 @@
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<media::AudioMixerAttributesInternal> _aidlReturn;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2696,8 +2696,8 @@
return PERMISSION_DENIED;
}
- media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+ media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
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 f01b653..359c140 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -178,8 +178,8 @@
auto result = [&]() -> ConversionResult<bool> {
media::audio::common::AudioConfigBase configAidl = VALUE_OR_RETURN(
legacy2aidl_audio_config_base_t_AudioConfigBase(config, false /*isInput*/));
- media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN(
- legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
+ media::audio::common::AudioAttributes attributesAidl = VALUE_OR_RETURN(
+ legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
bool retAidl;
RETURN_IF_ERROR(aidl_utils::statusTFromBinderStatus(
aps->isDirectOutputSupported(configAidl, attributesAidl, &retAidl)));
diff --git a/media/libaudioclient/AudioVolumeGroup.cpp b/media/libaudioclient/AudioVolumeGroup.cpp
index 978599e..c4ca5b9 100644
--- a/media/libaudioclient/AudioVolumeGroup.cpp
+++ b/media/libaudioclient/AudioVolumeGroup.cpp
@@ -49,9 +49,9 @@
aidl.groupId = VALUE_OR_RETURN(legacy2aidl_volume_group_t_int32_t(legacy.getId()));
aidl.name = legacy.getName();
aidl.audioAttributes = VALUE_OR_RETURN(
- convertContainer<std::vector<media::AudioAttributesInternal>>(
+ convertContainer<std::vector<media::audio::common::AudioAttributes>>(
legacy.getAudioAttributes(),
- legacy2aidl_audio_attributes_t_AudioAttributesInternal));
+ legacy2aidl_audio_attributes_t_AudioAttributes));
aidl.streams = VALUE_OR_RETURN(
convertContainer<std::vector<AudioStreamType>>(legacy.getStreamTypes(),
legacy2aidl_audio_stream_type_t_AudioStreamType));
@@ -65,7 +65,7 @@
VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
VALUE_OR_RETURN(convertContainer<AttributesVector>(
aidl.audioAttributes,
- aidl2legacy_AudioAttributesInternal_audio_attributes_t)),
+ aidl2legacy_AudioAttributes_audio_attributes_t)),
VALUE_OR_RETURN(convertContainer<StreamTypeVector>(
aidl.streams,
aidl2legacy_AudioStreamType_audio_stream_type_t))
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 7b33a00..7caaaaf 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -56,7 +56,7 @@
ConversionResult<media::CreateTrackRequest> IAudioFlinger::CreateTrackInput::toAidl() const {
media::CreateTrackRequest aidl;
- aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributes(attr));
// Do not be mislead by 'Input'--this is an input to 'createTrack', which creates output tracks.
aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_t_AudioConfig(
config, false /*isInput*/));
@@ -77,7 +77,7 @@
ConversionResult<IAudioFlinger::CreateTrackInput>
IAudioFlinger::CreateTrackInput::fromAidl(const media::CreateTrackRequest& aidl) {
IAudioFlinger::CreateTrackInput legacy;
- legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+ legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributes_audio_attributes_t(aidl.attr));
// Do not be mislead by 'Input'--this is an input to 'createTrack', which creates output tracks.
legacy.config = VALUE_OR_RETURN(
aidl2legacy_AudioConfig_audio_config_t(aidl.config, false /*isInput*/));
@@ -153,7 +153,7 @@
ConversionResult<media::CreateRecordRequest>
IAudioFlinger::CreateRecordInput::toAidl() const {
media::CreateRecordRequest aidl;
- aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+ aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributes(attr));
aidl.config = VALUE_OR_RETURN(
legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/));
aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
@@ -174,7 +174,7 @@
const media::CreateRecordRequest& aidl) {
IAudioFlinger::CreateRecordInput legacy;
legacy.attr = VALUE_OR_RETURN(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+ aidl2legacy_AudioAttributes_audio_attributes_t(aidl.attr));
legacy.config = VALUE_OR_RETURN(
aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config, true /*isInput*/));
legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
diff --git a/media/libaudioclient/VolumeGroupAttributes.cpp b/media/libaudioclient/VolumeGroupAttributes.cpp
index 530e73f..938e574 100644
--- a/media/libaudioclient/VolumeGroupAttributes.cpp
+++ b/media/libaudioclient/VolumeGroupAttributes.cpp
@@ -48,7 +48,7 @@
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 @@
return VolumeGroupAttributes(VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
aidl.streamType)),
- VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(
+ VALUE_OR_RETURN(aidl2legacy_AudioAttributes_audio_attributes_t(
aidl.attributes)));
}
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
index 335866f..7827bdb 100644
--- a/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioStreamType;
/**
@@ -24,7 +24,7 @@
* {@hide}
*/
parcelable AudioAttributesEx {
- AudioAttributesInternal attributes;
+ AudioAttributes attributes;
AudioStreamType streamType;
/** Interpreted as volume_group_t. */
int groupId;
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
deleted file mode 100644
index 2e74206..0000000
--- a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.media.audio.common.AudioContentType;
-import android.media.audio.common.AudioSource;
-import android.media.audio.common.AudioUsage;
-
-/**
- * The "Internal" suffix of this type name is to disambiguate it from the
- * android.media.AudioAttributes SDK type.
- * {@hide}
- */
-parcelable AudioAttributesInternal {
- AudioContentType contentType;
- AudioUsage usage;
- AudioSource source;
- // Bitmask, indexed by AudioFlag.
- int flags;
- @utf8InCpp String tags; /* UTF8 */
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioFlag.aidl b/media/libaudioclient/aidl/android/media/AudioFlag.aidl
deleted file mode 100644
index acf4e6d..0000000
--- a/media/libaudioclient/aidl/android/media/AudioFlag.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioFlag {
- AUDIBILITY_ENFORCED = 0,
- SECURE = 1,
- SCO = 2,
- BEACON = 3,
- HW_AV_SYNC = 4,
- HW_HOTWORD = 5,
- BYPASS_INTERRUPTION_POLICY = 6,
- BYPASS_MUTE = 7,
- LOW_LATENCY = 8,
- DEEP_BUFFER = 9,
- NO_MEDIA_PROJECTION = 10,
- MUTE_HAPTIC = 11,
- NO_SYSTEM_CAPTURE = 12,
- CAPTURE_PRIVATE = 13,
- CONTENT_SPATIALIZED = 14,
- NEVER_SPATIALIZE = 15,
- CALL_REDIRECTION = 16,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
index b95a1d3..424f8b8 100644
--- a/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioStreamType;
/**
@@ -26,6 +26,6 @@
/** Interpreted as volume_group_t. */
int groupId;
@utf8InCpp String name;
- AudioAttributesInternal[] audioAttributes;
+ AudioAttributes[] audioAttributes;
AudioStreamType[] streams;
}
diff --git a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
index b938a3e..57e8f42 100644
--- a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
@@ -16,8 +16,8 @@
package android.media;
-import android.media.AudioAttributesInternal;
import android.media.AudioClient;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioConfigBase;
/**
@@ -28,7 +28,7 @@
* {@hide}
*/
parcelable CreateRecordRequest {
- AudioAttributesInternal attr;
+ AudioAttributes attr;
AudioConfigBase config;
AudioClient clientInfo;
/** Interpreted as audio_unique_id_t. */
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
index 212221e..24e6a6c 100644
--- a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
@@ -16,7 +16,7 @@
package android.media;
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
import android.media.AudioClient;
import android.media.IAudioTrackCallback;
import android.media.SharedFileRegion;
@@ -30,7 +30,7 @@
* {@hide}
*/
parcelable CreateTrackRequest {
- AudioAttributesInternal attr;
+ AudioAttributes attr;
AudioConfig config;
AudioClient clientInfo;
@nullable SharedFileRegion sharedBuffer;
diff --git a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
index 9d44bb0..b814b85 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 @@
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 90ede8b..3e9b27f 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -18,8 +18,6 @@
import android.content.AttributionSourceState;
-import android.media.AudioAttributesEx;
-import android.media.AudioAttributesInternal;
import android.media.AudioDirectMode;
import android.media.AudioMix;
import android.media.AudioMixerAttributesInternal;
@@ -43,6 +41,7 @@
import android.media.ICaptureStateListener;
import android.media.INativeSpatializerCallback;
import android.media.SoundTriggerSession;
+import android.media.audio.common.AudioAttributes;
import android.media.audio.common.AudioConfig;
import android.media.audio.common.AudioConfigBase;
import android.media.audio.common.AudioDevice;
@@ -85,7 +84,7 @@
int /* audio_io_handle_t */ getOutput(AudioStreamType stream);
- GetOutputForAttrResponse getOutputForAttr(in AudioAttributesInternal attr,
+ GetOutputForAttrResponse getOutputForAttr(in AudioAttributes attr,
int /* audio_session_t */ session,
in AttributionSourceState attributionSource,
in AudioConfig config,
@@ -98,7 +97,7 @@
void releaseOutput(int /* audio_port_handle_t */ portId);
- GetInputForAttrResponse getInputForAttr(in AudioAttributesInternal attr,
+ GetInputForAttrResponse getInputForAttr(in AudioAttributes attr,
int /* audio_io_handle_t */ input,
int /* audio_unique_id_t */ riid,
int /* audio_session_t */ session,
@@ -125,20 +124,20 @@
int getStreamVolumeIndex(AudioStreamType stream,
in AudioDeviceDescription device);
- void setVolumeIndexForAttributes(in AudioAttributesInternal attr,
+ void setVolumeIndexForAttributes(in AudioAttributes attr,
in AudioDeviceDescription device,
int index);
- int getVolumeIndexForAttributes(in AudioAttributesInternal attr,
+ int getVolumeIndexForAttributes(in AudioAttributes attr,
in AudioDeviceDescription device);
- int getMaxVolumeIndexForAttributes(in AudioAttributesInternal attr);
+ int getMaxVolumeIndexForAttributes(in AudioAttributes attr);
- int getMinVolumeIndexForAttributes(in AudioAttributesInternal attr);
+ int getMinVolumeIndexForAttributes(in AudioAttributes attr);
int /* product_strategy_t */ getStrategyForStream(AudioStreamType stream);
- AudioDevice[] getDevicesForAttributes(in AudioAttributesInternal attr, boolean forVolume);
+ AudioDevice[] getDevicesForAttributes(in AudioAttributes attr, boolean forVolume);
int /* audio_io_handle_t */ getOutputForEffect(in EffectDescriptor desc);
@@ -200,7 +199,7 @@
* Check if direct playback is possible for given format, sample rate, channel mask and flags.
*/
boolean isDirectOutputSupported(in AudioConfigBase config,
- in AudioAttributesInternal attributes);
+ in AudioAttributes attributes);
/**
* List currently attached audio ports and their attributes. Returns the generation.
@@ -272,7 +271,7 @@
void removeUserIdDeviceAffinities(int userId);
int /* audio_port_handle_t */ startAudioSource(in AudioPortConfigFw source,
- in AudioAttributesInternal attributes);
+ in AudioAttributes attributes);
void stopAudioSource(int /* audio_port_handle_t */ portId);
@@ -333,10 +332,10 @@
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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 b0d48b7..10f6d4a 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -21,10 +21,8 @@
#include <system/audio.h>
-#include <android/media/AudioAttributesInternal.h>
#include <android/media/AudioClient.h>
#include <android/media/AudioDirectMode.h>
-#include <android/media/AudioFlag.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
#include <android/media/AudioPortFw.h>
@@ -105,21 +103,6 @@
ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
const AudioClient& legacy);
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
-ConversionResult<media::AudioFlag>
-legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
-
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
-
-ConversionResult<audio_attributes_t>
-aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl);
-ConversionResult<media::AudioAttributesInternal>
-legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
-
ConversionResult<sp<IMemory>>
aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
ConversionResult<media::SharedFileRegion>
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 0d12f9d..976a532 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -94,6 +94,11 @@
AudioChannelLayout::LAYOUT_STEREO);
}
+AudioChannelLayout make_ACL_Tri() {
+ return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+ AudioChannelLayout::LAYOUT_TRI);
+}
+
AudioChannelLayout make_ACL_LayoutArbitrary() {
return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
// Use channels that exist both for input and output,
@@ -311,8 +316,8 @@
AudioChannelLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
testing::Combine(
testing::Values(AudioChannelLayout{}, make_ACL_Invalid(), make_ACL_Stereo(),
- make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
- make_ACL_ChannelIndexArbitrary(),
+ make_ACL_Tri(), make_ACL_LayoutArbitrary(),
+ make_ACL_ChannelIndex2(), make_ACL_ChannelIndexArbitrary(),
AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
AudioChannelLayout::CHANNEL_FRONT_LEFT),
AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
diff --git a/media/libaudioclient/tests/audioclient_serialization_tests.cpp b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
index d1e3d16..707b9b3 100644
--- a/media/libaudioclient/tests/audioclient_serialization_tests.cpp
+++ b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
@@ -103,7 +103,7 @@
attr.usage = kUsages[rand() % kUsages.size()];
attr.source = kInputSources[rand() % kInputSources.size()];
// attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)]
- attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3fff);
+ attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3ffd); // exclude AUDIO_FLAG_SECURE
sprintf(attr.tags, "%s",
CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str());
}
@@ -119,6 +119,7 @@
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<VolumeGroupAttributes> volumeGroupAttrVector;
for (auto i = 0; i < 16; i++) {
audio_attributes_t attributes;
@@ -132,20 +133,19 @@
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/media/libaudiohal/TEST_MAPPING b/media/libaudiohal/TEST_MAPPING
index 5d3fb0a..90f481b 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/Android.bp b/media/libaudiohal/impl/Android.bp
index 09e70eb..1689365 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -245,20 +245,48 @@
]
}
-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",
+ "av-audio-types-aidl-ndk",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudio_aidl_conversion_common_ndk_cpp",
+ "libaudio_aidl_conversion_core_ndk",
+ "libaudio_aidl_conversion_effect_ndk",
+ "libaudioaidlcommon",
+ "libbinder_ndk",
+ ],
+ header_libs: [
+ "libaudio_system_headers",
+ "libeffectsconfig_headers",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wthread-safety",
+ "-DBACKEND_CPP_NDK",
+ ],
+}
+
+cc_library_shared {
+ name: "libaudiohal@aidl",
+ defaults: [
+ "libaudiohal_default",
+ "libaudiohal_aidl_default",
+ ],
srcs: [
- "DeviceHalAidl.cpp",
"DevicesFactoryHalEntry.cpp",
- "DevicesFactoryHalAidl.cpp",
"EffectConversionHelperAidl.cpp",
"EffectBufferHalAidl.cpp",
"EffectHalAidl.cpp",
@@ -280,32 +308,18 @@
"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: [
+ "ConversionHelperAidl.cpp",
+ "DeviceHalAidl.cpp",
+ "DevicesFactoryHalAidl.cpp",
"StreamHalAidl.cpp",
- ":audio_effectproxy_src_files"
- ],
- static_libs: [
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
- ],
- shared_libs: [
- "libaudio_aidl_conversion_common_cpp",
- "libaudio_aidl_conversion_common_ndk",
- "libaudio_aidl_conversion_common_ndk_cpp",
- "libaudio_aidl_conversion_core_ndk",
- "libaudio_aidl_conversion_effect_ndk",
- "libaudioaidlcommon",
- "libbinder_ndk",
- ],
- header_libs: [
- "libaudio_system_headers",
- "libeffectsconfig_headers",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wthread-safety",
- "-DBACKEND_CPP_NDK",
],
}
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
new file mode 100644
index 0000000..7197bf2
--- /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 <memory>
+
+#include <media/AidlConversionUtil.h>
+#include <utils/Log.h>
+
+#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<IHalAdapterVendorExtension> 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<std::string> parameterIds;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
+ ParameterScope(recipient.index()),
+ std::string(rawKeys.c_str()), ¶meterIds)));
+ if (parameterIds.empty()) return OK;
+
+ std::vector<VendorParameter> parameters;
+ if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+ auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters(
+ parameterIds, ¶meters)));
+ } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+ auto stream = std::get<static_cast<int>(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<IHalAdapterVendorExtension> 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<VendorParameter> syncParameters, asyncParameters;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
+ ParameterScope(recipient.index()),
+ std::string(rawKeysAndValues.c_str()),
+ &syncParameters, &asyncParameters)));
+ if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+ auto module = std::get<static_cast<int>(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<int>(ParameterScope::STREAM)) {
+ auto stream = std::get<static_cast<int>(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 5534d13..0fadd9c 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -18,8 +18,12 @@
#include <string>
#include <string_view>
+#include <variant>
#include <vector>
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/IStreamCommon.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <android-base/expected.h>
#include <error/Result.h>
#include <media/AudioParameter.h>
@@ -74,4 +78,18 @@
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 3125e311..ae15190 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -32,6 +32,7 @@
#include <utils/Log.h>
#include "DeviceHalAidl.h"
+#include "EffectHalAidl.h"
#include "StreamHalAidl.h"
using aidl::android::aidl_utils::statusTFromBinderStatus;
@@ -62,6 +63,7 @@
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 +78,7 @@
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 +128,10 @@
} // namespace
-DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext)
: ConversionHelperAidl("DeviceHalAidl"),
- mInstance(instance), mModule(module),
+ mInstance(instance), mModule(module), mVendorExt(vext),
mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
@@ -135,11 +139,8 @@
}
status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
- auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
- return ndk2cpp_AudioPort(pair.second);
- };
- return ::aidl::android::convertRange(mPorts.begin(), mPorts.end(), ports->begin(),
- convertAudioPortFromMap);
+ return ::aidl::android::convertContainer(mPorts, ports,
+ [](const Ports::value_type& pair) { return ndk2cpp_AudioPort(pair.second); });
}
status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
@@ -289,19 +290,24 @@
if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
}
-
- ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"",
- __func__, parameters.toString().c_str());
- return OK;
+ if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
+ ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
+ }
+ 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 +577,7 @@
return NO_INIT;
}
*outStream = sp<StreamOutHalAidl>::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 +638,7 @@
return NO_INIT;
}
*inStream = sp<StreamInHalAidl>::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;
@@ -877,25 +883,64 @@
return OK;
}
-status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
- sp<EffectHalInterface> effect) {
+status_t DeviceHalAidl::addDeviceEffect(
+ const struct audio_port_config *device, sp<EffectHalInterface> 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<effect::EffectHalAidl>::cast(effect);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->addDeviceEffect(
+ devicePortConfig.id, aidlEffect->getIEffect())));
+ cleanups.disarmAll();
return OK;
}
-status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
- sp<EffectHalInterface> effect) {
+status_t DeviceHalAidl::removeDeviceEffect(
+ const struct audio_port_config *device, sp<EffectHalInterface> 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<AudioPortExt::Tag::device>().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<effect::EffectHalAidl>::cast(effect);
+ return statusTFromBinderStatus(mModule->removeDeviceEffect(
+ existingPortConfigIt->first, aidlEffect->getIEffect()));
}
status_t DeviceHalAidl::getMmapPolicyInfos(
@@ -1112,9 +1157,23 @@
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<bool> a2dpEnabled;
+ std::optional<std::vector<VendorParameter>> reconfigureOffload;
(void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
parameters, String8(AudioParameter::keyBtA2dpSuspended),
[&a2dpEnabled](const String8& trueOrFalse) {
@@ -1129,10 +1188,27 @@
AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
return BAD_VALUE;
}));
- // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyReconfigA2dp),
+ [&](const String8& value) -> status_t {
+ if (mVendorExt != nullptr) {
+ std::vector<VendorParameter> result;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ mVendorExt->parseBluetoothA2dpReconfigureOffload(
+ std::string(value.c_str()), &result)));
+ reconfigureOffload = std::move(result);
+ } else {
+ reconfigureOffload = std::vector<VendorParameter>();
+ }
+ 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;
}
@@ -1256,6 +1332,44 @@
return OK;
}
+status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter ¶meters) {
+ TIME_CHECK();
+ (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+ parameters, String8(AudioParameter::keyScreenState),
+ [&](const String8& onOrOff) -> status_t {
+ std::optional<bool> 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<int>(
+ 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<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 37d800b..74a8b51 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -20,6 +20,7 @@
#include <set>
#include <vector>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <aidl/android/hardware/audio/core/BpModule.h>
#include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
#include <android-base/thread_annotations.h>
@@ -148,9 +149,11 @@
// List microphones
status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
- status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+ status_t addDeviceEffect(
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) override;
- status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+ status_t removeDeviceEffect(
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) override;
status_t getMmapPolicyInfos(media::audio::common::AudioMMapPolicyType policyType __unused,
std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos
@@ -203,7 +206,8 @@
// 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,10 +218,12 @@
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);
status_t filterAndUpdateBtScoParameters(AudioParameter ¶meters);
+ status_t filterAndUpdateScreenParameters(AudioParameter ¶meters);
status_t findOrCreatePatch(
const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds,
@@ -291,6 +297,7 @@
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/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 826461f..f96d419 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -32,6 +32,7 @@
#include <util/CoreUtils.h>
#include "DeviceHalHidl.h"
+#include "EffectHalHidl.h"
#include "ParameterUtils.h"
#include "StreamHalHidl.h"
@@ -523,30 +524,32 @@
#if MAJOR_VERSION >= 6
status_t DeviceHalHidl::addDeviceEffect(
- audio_port_handle_t device, sp<EffectHalInterface> effect) {
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) {
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
+ auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
return processReturn("addDeviceEffect", mDevice->addDeviceEffect(
- static_cast<AudioPortHandle>(device), effect->effectId()));
+ static_cast<AudioPortHandle>(device->id), hidlEffect->effectId()));
}
#else
status_t DeviceHalHidl::addDeviceEffect(
- audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
+ const struct audio_port_config *device __unused, sp<EffectHalInterface> effect __unused) {
return INVALID_OPERATION;
}
#endif
#if MAJOR_VERSION >= 6
status_t DeviceHalHidl::removeDeviceEffect(
- audio_port_handle_t device, sp<EffectHalInterface> effect) {
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) {
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
+ auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
return processReturn("removeDeviceEffect", mDevice->removeDeviceEffect(
- static_cast<AudioPortHandle>(device), effect->effectId()));
+ static_cast<AudioPortHandle>(device->id), hidlEffect->effectId()));
}
#else
status_t DeviceHalHidl::removeDeviceEffect(
- audio_port_handle_t device __unused, sp<EffectHalInterface> effect __unused) {
+ const struct audio_port_config *device __unused, sp<EffectHalInterface> effect __unused) {
return INVALID_OPERATION;
}
#endif
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index c5addde..989c1f5 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -105,8 +105,10 @@
// List microphones
status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
- status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
- status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+ status_t addDeviceEffect(
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) override;
+ status_t removeDeviceEffect(
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) override;
status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType __unused,
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 8345cd2..f00b1a0 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -34,7 +34,8 @@
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 {
@@ -83,25 +84,16 @@
if (name == nullptr || device == nullptr) {
return BAD_VALUE;
}
-
- // FIXME: Remove this call and the check for the supported module names
- // after implementing retrieval of module names on the framework side.
- // Currently it is still using the legacy XML config.
- std::vector<std::string> deviceNames;
- if (status_t status = getDeviceNames(&deviceNames); status != OK) {
- return status;
- }
std::shared_ptr<IModule> service;
- if (std::find(deviceNames.begin(), deviceNames.end(), name) != deviceNames.end()) {
- if (strcmp(name, "primary") == 0) name = "default";
- auto serviceName = std::string(IModule::descriptor) + "/" + name;
- service = IModule::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
- ALOGE_IF(service == nullptr, "%s fromBinder %s failed", __func__, serviceName.c_str());
+ if (strcmp(name, "primary") == 0) name = "default";
+ auto serviceName = std::string(IModule::descriptor) + "/" + name;
+ service = IModule::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+ if (service == nullptr) {
+ ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
+ return NO_INIT;
}
- // If the service is a nullptr, the device object will not be really functional,
- // but will not crash either.
- *device = sp<DeviceHalAidl>::make(name, service);
+ *device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
return OK;
}
@@ -163,6 +155,20 @@
return OK;
}
+std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
+ if (!mVendorExt.has_value()) {
+ auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
+ if (AServiceManager_isDeclared(serviceName.c_str())) {
+ mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
+ 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 21957bc..97e3796 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -17,6 +17,7 @@
#pragma once
#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <media/audiohal/DevicesFactoryHalInterface.h>
#include <utils/RefBase.h>
@@ -46,6 +47,11 @@
private:
const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
+ std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
+ mVendorExt;
+
+ std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension();
+
~DevicesFactoryHalAidl() = default;
};
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 52fed91..8a582a5 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -72,14 +72,13 @@
EffectConversionHelperAidl::EffectConversionHelperAidl(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> 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;
@@ -195,11 +194,9 @@
statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn)));
if (mIsProxyEffect) {
- const auto& ret =
- std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
- mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
- mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
- mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+ mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ();
+ mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ();
+ mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ();
} else {
mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
@@ -207,6 +204,7 @@
}
if (status_t status = updateEventFlags(); status != OK) {
+ ALOGV("%s closing at status %d", __func__, status);
mEffect->close();
return status;
}
@@ -319,17 +317,25 @@
mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
return *static_cast<int32_t*>(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<Parameter::volumeStereo>(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;
}
@@ -346,14 +352,15 @@
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<EffectProxy>(mEffect)->setOffloadParam(offload)));
- // update FMQs
- const auto& ret = std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
- mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
- mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
- mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
- RETURN_STATUS_IF_ERROR(updateEventFlags());
+ const auto& effectProxy = std::static_pointer_cast<EffectProxy>(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<int32_t*>(pReplyData) = OK;
}
@@ -401,17 +408,27 @@
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<EffectProxy>(mEffect)->isBypassing()));
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 0c682ff..7c8f11b 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -41,6 +41,7 @@
std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
+ bool isBypassing() const;
protected:
const int32_t mSessionId;
@@ -54,7 +55,7 @@
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/EffectConversionHelperHidl.h b/media/libaudiohal/impl/EffectConversionHelperHidl.h
index 4371d12..ed696bf 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 faf5f45..ae4a530 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -61,12 +61,11 @@
namespace effect {
EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
- const std::shared_ptr<IEffect>& effect, uint64_t effectId,
+ const std::shared_ptr<IEffect>& effect,
int32_t sessionId, int32_t ioId, const Descriptor& desc,
bool isProxyEffect)
: mFactory(factory),
mEffect(effect),
- mEffectId(effectId),
mSessionId(sessionId),
mIoId(ioId),
mDesc(desc),
@@ -76,8 +75,11 @@
EffectHalAidl::~EffectHalAidl() {
if (mEffect) {
- mIsProxyEffect ? std::static_pointer_cast<EffectProxy>(mEffect)->destroy()
- : mFactory->destroyEffect(mEffect);
+ if (mIsProxyEffect) {
+ std::static_pointer_cast<EffectProxy>(mEffect)->destroy();
+ } else if (mFactory) {
+ mFactory->destroyEffect(mEffect);
+ }
}
}
@@ -89,64 +91,64 @@
ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
- mConversion =
- std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId,
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::
getEffectTypeUuidAutomaticGainControlV1()) {
mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
- desc);
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::
getEffectTypeUuidAutomaticGainControlV2()) {
mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
- desc);
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
- mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
- mConversion = std::make_unique<android::effect::AidlConversionDownmix>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionDownmix>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
- mConversion =
- std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId,
+ desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
- mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
- mConversion =
- std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId,
+ desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
- mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(effect, sessionId,
- ioId, desc);
+ mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(
+ effect, sessionId, ioId, desc, mIsProxyEffect);
} else {
// For unknown UUID, use vendor extension implementation
mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
- effect, sessionId, ioId, desc);
+ effect, sessionId, ioId, desc, mIsProxyEffect);
}
return OK;
}
@@ -167,6 +169,9 @@
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/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 47049d7..1b7a3d6 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -56,13 +56,8 @@
// 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 @@
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 @@
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 94dcd7e..dda21ed 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 <media/audiohal/EffectHalInterface.h>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
@@ -31,7 +31,7 @@
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 @@
// 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/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index b61532d..fac03b7 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -15,15 +15,18 @@
*/
#include <algorithm>
+#include <iterator>
#include <memory>
#define LOG_TAG "EffectProxy"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#include <fmq/AidlMessageQueue.h>
+#include <system/audio_aidl_utils.h>
#include <utils/Log.h>
#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,17 +36,28 @@
using ::aidl::android::hardware::audio::effect::State;
using ::aidl::android::media::audio::common::AudioUuid;
-namespace android {
-namespace effect {
+namespace android::effect {
-EffectProxy::EffectProxy(const Descriptor::Identity& id, const std::shared_ptr<IFactory>& 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)),
+EffectProxy::EffectProxy(const AudioUuid& uuid, const std::vector<Descriptor>& descriptors,
+ const std::shared_ptr<IFactory>& factory)
+ : mDescriptorCommon(buildDescriptorCommon(uuid, descriptors)),
+ mSubEffects(
+ [](const std::vector<Descriptor>& descs, const std::shared_ptr<IFactory>& factory) {
+ std::vector<SubEffect> 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) {
+ sub.handle = nullptr;
+ 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() {
@@ -52,68 +66,9 @@
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__, mIdentity.type.toString().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<SubEffectTupleIndex::HANDLE>(mSubEffects[sub.common.id]) = nullptr;
- std::get<SubEffectTupleIndex::DESCRIPTOR>(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__, mIdentity.type.toString().c_str());
- ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
-
- for (auto& sub : mSubEffects) {
- auto& effectHandle = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- ALOGI("%s sub-effect %s", __func__, sub.first.uuid.toString().c_str());
- status = mFactory->createEffect(sub.first.uuid, &effectHandle);
- if (!status.isOk() || !effectHandle) {
- ALOGE("%s sub-effect failed %s", __func__, sub.first.uuid.toString().c_str());
- break;
- }
- }
-
- // destroy all created effects if failure
- if (!status.isOk()) {
- destroy();
- }
- return status;
-}
-
ndk::ScopedAStatus EffectProxy::destroy() {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ALOGV("%s: %s", __func__,
+ ::android::audio::utils::toString(mDescriptorCommon.id.type).c_str());
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
if (status.isOk()) {
@@ -123,28 +78,24 @@
});
}
-const IEffect::OpenEffectReturn* EffectProxy::getEffectReturnParam() {
- return &std::get<SubEffectTupleIndex::RETURN>(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<SubEffectTupleIndex::DESCRIPTOR>(sub.second);
- ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload,
- desc.common.id.uuid.toString().c_str(), desc.common.flags.toString().c_str());
+ 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-", mActiveSub.uuid.toString().c_str(),
- std::get<SubEffectTupleIndex::DESCRIPTOR>(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();
}
@@ -152,20 +103,24 @@
ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
IEffect::OpenEffectReturn* ret __unused) {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
for (auto& sub : mSubEffects) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- auto& openRet = std::get<SubEffectTupleIndex::RETURN>(sub.second);
- if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) {
- ALOGE("%s: failed to open UUID %s", __func__, sub.first.uuid.toString().c_str());
+ 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<StatusMQ>(openReturn.statusMQ);
+ sub.effectMq.inputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
+ sub.effectMq.outputQ = std::make_shared<DataMQ>(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();
}
@@ -173,38 +128,69 @@
}
ndk::ScopedAStatus EffectProxy::close() {
- ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& 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<Descriptor>& 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<SubEffectTupleIndex::HANDLE>(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<SubEffectTupleIndex::DESCRIPTOR>(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<Descriptor>& subEffectDescs) {
+ Descriptor::Common common;
+
+ for (const auto& desc : subEffectDescs) {
+ if (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) {
+ common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
+ }
+
+ // 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;
+ }
+
+ // 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;
+
+ // 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__, mIdentity.type.toString().c_str(),
- android::internal::ToString(id).c_str());
return runWithActiveSubEffectThenOthers(
[&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
return effect->command(id);
@@ -239,34 +225,30 @@
std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> 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<SubEffectTupleIndex::HANDLE>(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<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(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(
@@ -274,12 +256,11 @@
ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
// proceed with others if active sub-effect success
for (auto& sub : mSubEffects) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(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());
}
@@ -287,5 +268,34 @@
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<IEffect>& 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.get(),
+ 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 ffb8a19..18e1567 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -40,27 +40,10 @@
*/
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 @@
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 @@
const ::aidl::android::hardware::audio::effect::Parameter::Id& id,
::aidl::android::hardware::audio::effect::Parameter* param) override;
+ 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<StatusMQ>& getStatusMQ() const {
+ return mSubEffects[mActiveSubIdx].effectMq.statusQ;
+ }
+ const std::shared_ptr<DataMQ>& getInputMQ() const {
+ return mSubEffects[mActiveSubIdx].effectMq.inputQ;
+ }
+ const std::shared_ptr<DataMQ>& 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;
+
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;
+ // 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<StatusMQ> statusQ;
+ std::shared_ptr<DataMQ> 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<SubEffect> mSubEffects;
+
const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
- // A map of sub effects descriptor to the IEffect handle and return FMQ
- enum SubEffectTupleIndex { HANDLE, DESCRIPTOR, RETURN };
- using EffectProxySub =
- std::tuple<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>,
- ::aidl::android::hardware::audio::effect::Descriptor,
- ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn>;
- std::map<const ::aidl::android::hardware::audio::effect::Descriptor::Identity, EffectProxySub>
- mSubEffects;
-
- // Descriptor of the only active effect in the mSubEffects map
- ::aidl::android::hardware::audio::effect::Descriptor::Identity mActiveSub;
-
- // 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<ndk::ScopedAStatus(
@@ -122,6 +137,12 @@
ndk::ScopedAStatus runWithAllSubEffects(
std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> 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 7b9088e..57395fa 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -28,6 +28,7 @@
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionEffect.h>
#include <system/audio.h>
+#include <system/audio_aidl_utils.h>
#include <utils/Log.h>
#include "EffectBufferHalAidl.h"
@@ -43,6 +44,7 @@
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;
@@ -66,26 +68,28 @@
}
return list;
}()),
- mUuidProxyMap([this]() {
- std::map<AudioUuid, std::shared_ptr<EffectProxy>> proxyMap;
+ mProxyUuidDescriptorMap([this]() {
+ std::map<AudioUuid, std::vector<Descriptor>> proxyUuidMap;
for (const auto& desc : mHalDescList) {
- // create EffectProxy
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<EffectProxy>(desc.common.id,
- mFactory)});
+ 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<Descriptor> 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));
}
}
@@ -116,7 +120,8 @@
}
*pNumEffects = mEffectCount;
- ALOGI("%s %d", __func__, *pNumEffects);
+ ALOGD("%s %u non %zu proxyMap %zu proxyDesc %zu", __func__, *pNumEffects,
+ mNonProxyDescList.size(), mProxyUuidDescriptorMap.size(), mProxyDescList.size());
return OK;
}
@@ -181,38 +186,31 @@
// 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<EffectProxy>(
+ aidlUuid, mProxyUuidDescriptorMap.at(aidlUuid) /* sub-effect descriptor list */,
+ mFactory);
+ mProxyList.emplace_back(std::static_pointer_cast<EffectProxy>(aidlEffect));
} else {
RETURN_STATUS_IF_ERROR(
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;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc)));
- uint64_t effectId;
- {
- std::lock_guard lg(mLock);
- effectId = ++mEffectIdCounter;
- }
-
- *effect =
- sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc, isProxy);
+ *effect = sp<EffectHalAidl>::make(mFactory, aidlEffect, sessionId, ioId, desc, isProxy);
return OK;
}
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));
@@ -244,10 +242,10 @@
auto matchIt = std::find_if(list.begin(), list.end(),
[&](const auto& desc) { return desc.common.id.uuid == uuid; });
if (matchIt == list.end()) {
- ALOGE("%s UUID not found in HAL and proxy list %s", __func__, uuid.toString().c_str());
+ ALOGE("%s UUID not found in HAL and proxy list %s", __func__, toString(uuid).c_str());
return BAD_VALUE;
}
- ALOGI("%s UUID impl found %s", __func__, uuid.toString().c_str());
+ ALOGI("%s UUID impl found %s", __func__, toString(uuid).c_str());
*pDescriptor = VALUE_OR_RETURN_STATUS(
::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
@@ -266,10 +264,10 @@
std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
[&](auto& desc) { return desc.common.id.type == type; });
if (result.empty()) {
- ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, type.toString().c_str());
+ ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, toString(type).c_str());
return BAD_VALUE;
}
- ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), type.toString().c_str());
+ ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), toString(type).c_str());
*descriptors = VALUE_OR_RETURN_STATUS(
aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
@@ -278,7 +276,7 @@
}
bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const {
- return 0 != mUuidProxyMap.count(uuid);
+ return 0 != mProxyUuidDescriptorMap.count(uuid);
}
std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 39beea2..73089b0 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -17,8 +17,8 @@
#pragma once
#include <cstddef>
+#include <list>
#include <memory>
-#include <mutex>
#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <aidl/android/hardware/audio/effect/Processing.h>
@@ -72,10 +72,9 @@
const detail::AudioHalVersionInfo mHalVersion;
// Full list of HAL effect descriptors
const std::vector<Descriptor> 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<EffectProxy>>
- mUuidProxyMap;
+ // Map of proxy UUID (key) to the Descriptor of sub-effects
+ const std::map<::aidl::android::media::audio::common::AudioUuid, std::vector<Descriptor>>
+ mProxyUuidDescriptorMap;
// List of effect proxy, initialize after mUuidProxyMap because it need to have all sub-effects
const std::vector<Descriptor> mProxyDescList;
// List of non-proxy effects
@@ -85,16 +84,16 @@
// Query result of pre and post processing from effect factory
const std::vector<Processing> mAidlProcessings;
- std::mutex mLock;
- uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
+ // list of the EffectProxy instances
+ std::list<std::shared_ptr<EffectProxy>> 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<effect_descriptor_t>* descriptors);
bool isProxyEffect(const aidl::android::media::audio::common::AudioUuid& uuid) const;
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index d1044dc..80e19a0 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -32,6 +32,7 @@
#include <utils/Log.h>
#include "DeviceHalAidl.h"
+#include "EffectHalAidl.h"
#include "StreamHalAidl.h"
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
@@ -43,6 +44,7 @@
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 +75,14 @@
StreamHalAidl::StreamHalAidl(
std::string_view className, bool isInput, const audio_config& config,
int32_t nominalLatency, StreamContextAidl&& context,
- const std::shared_ptr<IStreamCommon>& stream)
+ const std::shared_ptr<IStreamCommon>& stream,
+ const std::shared_ptr<IHalAdapterVendorExtension>& 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 +129,6 @@
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 +137,18 @@
[&](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) {
@@ -160,20 +163,26 @@
return OK;
}
-status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
+status_t StreamHalAidl::addEffect(sp<EffectHalInterface> 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<effect::EffectHalAidl>::cast(effect);
+ return statusTFromBinderStatus(mStream->addEffect(aidlEffect->getIEffect()));
}
-status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
+status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> 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<effect::EffectHalAidl>::cast(effect);
+ return statusTFromBinderStatus(mStream->removeEffect(aidlEffect->getIEffect()));
}
status_t StreamHalAidl::standby() {
@@ -533,9 +542,11 @@
StreamOutHalAidl::StreamOutHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+ const std::shared_ptr<IStreamOut>& stream,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+ const sp<CallbackBroker>& 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<int32_t>(config.sample_rate);
@@ -861,9 +872,11 @@
StreamInHalAidl::StreamInHalAidl(
const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
- const std::shared_ptr<IStreamIn>& stream, const sp<MicrophoneInfoProvider>& micInfoProvider)
+ const std::shared_ptr<IStreamIn>& stream,
+ const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+ const sp<MicrophoneInfoProvider>& 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 75a1dd9..3b369bd 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -26,9 +26,11 @@
#include <aidl/android/hardware/audio/core/BpStreamIn.h>
#include <aidl/android/hardware/audio/core/BpStreamOut.h>
#include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
+#include <media/AidlConversionUtil.h>
#include <media/AudioParameter.h>
#include "ConversionHelperAidl.h"
@@ -48,7 +50,7 @@
typedef AidlMessageQueue<int8_t,
::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
- explicit StreamContextAidl(
+ StreamContextAidl(
::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
bool isAsynchronous)
: mFrameSizeBytes(descriptor.frameSizeBytes),
@@ -185,6 +187,9 @@
status_t legacyReleaseAudioPatch() override;
protected:
+ // For tests.
+ friend class sp<StreamHalAidl>;
+
template<class T>
static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
const std::shared_ptr<T>& stream);
@@ -195,7 +200,8 @@
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 @@
::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 @@
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>& callbackBroker);
~StreamOutHalAidl() override;
@@ -401,6 +409,7 @@
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<MicrophoneInfoProvider>& micInfoProvider);
~StreamInHalAidl() override = default;
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2b0af49..72eadc6 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -33,6 +33,7 @@
#include <util/CoreUtils.h>
#include "DeviceHalHidl.h"
+#include "EffectHalHidl.h"
#include "ParameterUtils.h"
#include "StreamHalHidl.h"
@@ -144,13 +145,15 @@
status_t StreamHalHidl::addEffect(sp<EffectHalInterface> effect) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- return processReturn("addEffect", mStream->addEffect(effect->effectId()));
+ auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
+ return processReturn("addEffect", mStream->addEffect(hidlEffect->effectId()));
}
status_t StreamHalHidl::removeEffect(sp<EffectHalInterface> effect) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- return processReturn("removeEffect", mStream->removeEffect(effect->effectId()));
+ auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
+ return processReturn("removeEffect", mStream->removeEffect(hidlEffect->effectId()));
}
status_t StreamHalHidl::standby() {
@@ -979,9 +982,10 @@
}
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/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
index 3ee419a..61dd36a 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
@@ -26,8 +26,9 @@
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 b0509fd..364b473 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
@@ -26,8 +26,9 @@
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 8f7eac7..df9a9ec 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
@@ -26,8 +26,9 @@
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 9664aa1..424b837 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
@@ -27,8 +27,8 @@
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 8b28ca3..f963f66 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
@@ -26,8 +26,9 @@
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 c5d5a54..62714c3 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
@@ -26,8 +26,9 @@
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 8b92374..95042eb 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
@@ -27,8 +27,8 @@
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.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index 45b98a1..fc867c7 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -161,6 +161,9 @@
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<Range::equalizer>();
for (const auto& r : ranges) {
if (r.min.getTag() == Equalizer::bandLevels &&
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
index f94556c..53566e2 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -25,9 +25,10 @@
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 03114a5..9890bfb 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
@@ -27,8 +27,8 @@
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 c0402f9..2ce14a6 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
@@ -27,8 +27,8 @@
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 f51e13a..fac121d 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
@@ -27,8 +27,8 @@
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 397d6e6..b975d72 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
@@ -27,8 +27,8 @@
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 c44567c..7c60b14 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
@@ -27,8 +27,8 @@
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 fd22e5c..16bfeba 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
@@ -27,8 +27,8 @@
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 91c0fcd..359d884 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
@@ -27,8 +27,8 @@
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 e380bc6..bc9320f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -27,8 +27,8 @@
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:
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 71e5e7a..a965709 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -132,9 +132,9 @@
std::vector<audio_microphone_characteristic_t>* microphones) = 0;
virtual status_t addDeviceEffect(
- audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) = 0;
virtual status_t removeDeviceEffect(
- audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
+ const struct audio_port_config *device, sp<EffectHalInterface> effect) = 0;
virtual status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType,
diff --git a/media/libaudiohal/include/media/audiohal/EffectHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
index 2969c92..cf8d7f0 100644
--- a/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectHalInterface.h
@@ -52,20 +52,14 @@
// 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/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 8210f7d..8f011c8 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -21,34 +21,34 @@
}
cc_defaults {
- name: "AudioHalTestDefaults",
+ name: "libaudiohal_aidl_test_default",
test_suites: ["device-tests"],
defaults: [
- "latest_android_media_audio_common_types_ndk_shared",
+ "libaudiohal_default",
+ "libaudiohal_aidl_default",
],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wthread-safety",
- "-DBACKEND_NDK",
- ],
-
shared_libs: [
- "audioclient-types-aidl-cpp",
- "libaudio_aidl_conversion_common_ndk",
"libaudiohal",
- "liblog",
- "libutils",
- "libvibrator",
],
}
cc_test {
+ name: "CoreAudioHalAidlTest",
+ srcs: [
+ "CoreAudioHalAidl_test.cpp",
+ ":core_audio_hal_aidl_src_files",
+ ],
+ defaults: ["libaudiohal_aidl_test_default"],
+ header_libs: ["libaudiohalimpl_headers"],
+}
+
+cc_test {
name: "EffectsFactoryHalInterfaceTest",
srcs: ["EffectsFactoryHalInterface_test.cpp"],
- defaults: ["AudioHalTestDefaults"],
- header_libs: ["libaudiohal_headers"],
+ defaults: ["libaudiohal_aidl_test_default"],
+ shared_libs: [
+ "libvibrator",
+ ],
}
cc_test {
@@ -58,15 +58,8 @@
":audio_effectproxy_src_files",
],
defaults: [
- "AudioHalTestDefaults",
- "latest_android_hardware_audio_effect_ndk_shared",
- "libaudiohal_default",
+ "libaudiohal_aidl_test_default",
"use_libaidlvintf_gtest_helper_static",
],
- shared_libs: [
- "android.hardware.common.fmq-V1-ndk",
- "libbinder_ndk",
- "libfmq",
- ],
header_libs: ["libaudiohalimpl_headers"],
}
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
new file mode 100644
index 0000000..ea20794
--- /dev/null
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "CoreAudioHalAidlTest"
+#include <gtest/gtest.h>
+
+#include <DeviceHalAidl.h>
+#include <StreamHalAidl.h>
+#include <aidl/android/hardware/audio/core/BnModule.h>
+#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
+#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
+#include <aidl/android/media/audio/common/Int.h>
+#include <utils/Log.h>
+
+namespace {
+
+using ::aidl::android::hardware::audio::core::VendorParameter;
+
+class VendorParameterMock {
+ public:
+ const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; }
+ const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; }
+ const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
+
+ protected:
+ ndk::ScopedAStatus getVendorParametersImpl(const std::vector<std::string>& in_parameterIds) {
+ mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(),
+ in_parameterIds.end());
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setVendorParametersImpl(const std::vector<VendorParameter>& 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<std::string> mGetParameterIds;
+ std::vector<VendorParameter> mAsyncParameters;
+ std::vector<VendorParameter> mSyncParameters;
+};
+
+class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
+ public VendorParameterMock {
+ public:
+ bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
+ ScreenRotation getScreenRotation() const { return mScreenRotation; }
+
+ private:
+ ndk::ScopedAStatus setModuleDebug(
+ const ::aidl::android::hardware::audio::core::ModuleDebug&) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getTelephony(
+ std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getBluetooth(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getBluetoothA2dp(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getBluetoothLe(
+ std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus connectExternalDevice(
+ const ::aidl::android::media::audio::common::AudioPort&,
+ ::aidl::android::media::audio::common::AudioPort*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus disconnectExternalDevice(int32_t) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPatches(
+ std::vector<::aidl::android::hardware::audio::core::AudioPatch>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPort(int32_t,
+ ::aidl::android::media::audio::common::AudioPort*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPortConfigs(
+ std::vector<::aidl::android::media::audio::common::AudioPortConfig>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioPorts(
+ std::vector<::aidl::android::media::audio::common::AudioPort>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioRoutes(
+ std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getAudioRoutesForAudioPort(
+ int32_t, std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus openInputStream(const OpenInputStreamArguments&,
+ OpenInputStreamReturn*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
+ OpenOutputStreamReturn*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setAudioPatch(const ::aidl::android::hardware::audio::core::AudioPatch&,
+ ::aidl::android::hardware::audio::core::AudioPatch*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setAudioPortConfig(
+ const ::aidl::android::media::audio::common::AudioPortConfig&,
+ ::aidl::android::media::audio::common::AudioPortConfig*, bool*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus resetAudioPatch(int32_t) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus resetAudioPortConfig(int32_t) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMasterMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus setMasterMute(bool) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMasterVolume(float*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus setMasterVolume(float) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMicMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus setMicMute(bool) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getMicrophones(
+ std::vector<::aidl::android::media::audio::common::MicrophoneInfo>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus updateAudioMode(::aidl::android::media::audio::common::AudioMode) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus updateScreenRotation(ScreenRotation in_rotation) override {
+ mScreenRotation = in_rotation;
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override {
+ mIsScreenTurnedOn = in_isTurnedOn;
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus getSoundDose(
+ std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>*)
+ override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+ std::vector<VendorParameter>*) override {
+ return getVendorParametersImpl(in_parameterIds);
+ }
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+ bool async) override {
+ return setVendorParametersImpl(in_parameters, async);
+ }
+ 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;
+};
+
+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<std::string>& in_parameterIds,
+ std::vector<VendorParameter>*) override {
+ return getVendorParametersImpl(in_parameterIds);
+ }
+ ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& 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<std::string>* _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<VendorParameter>* out_syncParameters,
+ std::vector<VendorParameter>* 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<VendorParameter>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&,
+ std::vector<VendorParameter>*) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
+ const std::vector<VendorParameter>& 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.c_str()), android::String8(value.c_str()));
+ return params.toString();
+}
+
+android::String8 createParameterString(const std::string& key, int value) {
+ android::AudioParameter params;
+ params.addInt(android::String8(key.c_str()), value);
+ return params.toString();
+}
+
+template <typename>
+struct mf_traits {};
+template <class T, class U>
+struct mf_traits<U T::*> {
+ using member_type = U;
+};
+
+} // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace aidl::android::hardware::audio::core {
+template <typename P>
+std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+ std::ostream&>
+operator<<(std::ostream& os, const P& p) {
+ return os << p.toString();
+}
+template <typename E>
+std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+ return os << toString(e);
+}
+} // namespace aidl::android::hardware::audio::core
+
+using namespace android;
+
+class DeviceHalAidlTest : public testing::Test {
+ public:
+ void SetUp() override {
+ mModule = ndk::SharedRefBase::make<ModuleMock>();
+ mDevice = sp<DeviceHalAidl>::make("test", mModule, nullptr /*vext*/);
+ }
+ void TearDown() override {
+ mDevice.clear();
+ mModule.reset();
+ }
+
+ protected:
+ std::shared_ptr<ModuleMock> mModule;
+ sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlTest, ScreenState) {
+ EXPECT_FALSE(mModule->isScreenTurnedOn());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+ AudioParameter::valueOn)));
+ EXPECT_TRUE(mModule->isScreenTurnedOn());
+ EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+ AudioParameter::valueOff)));
+ EXPECT_FALSE(mModule->isScreenTurnedOn());
+ // The adaptation layer only logs a warning.
+ EXPECT_EQ(OK, mDevice->setParameters(
+ createParameterString(AudioParameter::keyScreenState, "blah")));
+ EXPECT_FALSE(mModule->isScreenTurnedOn());
+}
+
+TEST_F(DeviceHalAidlTest, ScreenRotation) {
+ using ScreenRotation = ::aidl::android::hardware::audio::core::IModule::ScreenRotation;
+ EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+ EXPECT_EQ(OK,
+ mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 90)));
+ EXPECT_EQ(ScreenRotation::DEG_90, mModule->getScreenRotation());
+ EXPECT_EQ(OK,
+ mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 0)));
+ EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+ // The adaptation layer only logs a warning.
+ EXPECT_EQ(OK,
+ mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
+ EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+}
+
+// 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<ModuleMock>();
+ mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+ mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
+ }
+ void TearDown() override {
+ mDevice.clear();
+ mVendorExt.reset();
+ mModule.reset();
+ }
+
+ protected:
+ std::shared_ptr<ModuleMock> mModule;
+ std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+ sp<DeviceHalAidl> 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<StreamCommonMock>();
+ mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+ struct audio_config config = AUDIO_CONFIG_INITIALIZER;
+ ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
+ mStream = sp<StreamHalAidl>::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<StreamCommonMock> mStreamCommon;
+ std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+ sp<StreamHalAidl> 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());
+}
diff --git a/media/libaudiohal/tests/EffectProxy_test.cpp b/media/libaudiohal/tests/EffectProxy_test.cpp
index 92e3dce..8668e85 100644
--- a/media/libaudiohal/tests/EffectProxy_test.cpp
+++ b/media/libaudiohal/tests/EffectProxy_test.cpp
@@ -60,7 +60,7 @@
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 @@
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::shared_ptr<EffectProxy>, std::vector<Descriptor>>;
std::map<AudioUuid, EffectProxyTuple> createAllProxies() {
std::map<AudioUuid, EffectProxyTuple> 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<TupleIndex::HANDLE>(proxyMap[uuid]) =
- ndk::SharedRefBase::make<EffectProxy>(itor.first, mFactory);
+ ndk::SharedRefBase::make<EffectProxy>(itor.first, itor.second, mFactory);
}
}
return proxyMap;
}
- bool addAllSubEffects(std::map<AudioUuid, EffectProxyTuple> proxyMap) {
- for (auto& itor : mProxyDescs) {
- const auto& uuid = itor.first.proxy.value();
- if (proxyMap.end() == proxyMap.find(uuid)) {
- return false;
- }
- auto& proxy = std::get<TupleIndex::HANDLE>(proxyMap[uuid]);
- if (!proxy->addSubEffect(itor.second).isOk()) {
- return false;
- }
- std::get<TupleIndex::DESCRIPTOR>(proxyMap[uuid]).emplace_back(itor.second);
- }
- return true;
- }
-
std::shared_ptr<IFactory> mFactory;
std::vector<Descriptor> mDescs;
- std::map<Descriptor::Identity, Descriptor> mProxyDescs;
+ std::map<const AudioUuid, std::vector<Descriptor>> mProxyDescs;
};
TEST_F(EffectProxyTest, createProxy) {
@@ -144,24 +124,20 @@
TEST_F(EffectProxyTest, addSubEffectsCreateAndDestroy) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(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<TupleIndex::HANDLE>(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 @@
// 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<TupleIndex::HANDLE>(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<TupleIndex::HANDLE>(itor.second);
@@ -207,11 +173,9 @@
TEST_F(EffectProxyTest, closeWithoutOpen) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->close().isOk());
EXPECT_TRUE(proxy->destroy().isOk());
@@ -221,16 +185,6 @@
// 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 @@
Parameter expect;
auto& proxy = std::get<TupleIndex::HANDLE>(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 @@
// 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 @@
for (const auto& itor : proxyMap) {
Parameter expect;
auto& proxy = std::get<TupleIndex::HANDLE>(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 @@
// 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 @@
for (const auto& itor : proxyMap) {
Parameter expect;
auto& proxy = std::get<TupleIndex::HANDLE>(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 @@
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);
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 309765a..6160d7d 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -72,6 +72,10 @@
],
whole_static_libs: ["libaudioprocessing_base"],
+
+ export_shared_lib_headers: [
+ "libvibrator",
+ ],
}
cc_library_static {
diff --git a/media/libeffects/factory/EffectsConfigLoader.c b/media/libeffects/factory/EffectsConfigLoader.c
index e23530e..a1de7b3 100644
--- a/media/libeffects/factory/EffectsConfigLoader.c
+++ b/media/libeffects/factory/EffectsConfigLoader.c
@@ -137,7 +137,7 @@
kLibraryPathRoot[i],
lib_name);
if (F_OK == access(path, 0)) {
- strcpy(lib_path_out, path);
+ strlcpy(lib_path_out, path, PATH_MAX);
ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
"checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
return 0;
diff --git a/media/libeffects/factory/test/DumpConfig.cpp b/media/libeffects/factory/test/DumpConfig.cpp
index 0a156b4..331826f 100644
--- a/media/libeffects/factory/test/DumpConfig.cpp
+++ b/media/libeffects/factory/test/DumpConfig.cpp
@@ -14,54 +14,49 @@
* limitations under the License.
*/
+#include <getopt.h>
+
#include <media/EffectsFactoryApi.h>
-#include <unistd.h>
#include "EffectsXmlConfigLoader.h"
#include "EffectsConfigLoader.h"
int main(int argc, char* argv[]) {
- const char* path = nullptr;
- bool legacyFormat;
+ const char* const short_opts = "lx:h";
+ const option long_opts[] = {{"legacy", no_argument, nullptr, 'l'},
+ {"xml", optional_argument, nullptr, 'x'},
+ {"help", no_argument, nullptr, 'h'}};
- if (argc == 2 && strcmp(argv[1], "--legacy") == 0) {
- legacyFormat = true;
- fprintf(stderr, "Dumping legacy effect config file\n");
- } else if ((argc == 2 || argc == 3) && strcmp(argv[1], "--xml") == 0) {
- legacyFormat = false;
- if (argc == 3) {
- fprintf(stderr, "Dumping XML effect config file: %s\n", path);
- } else {
- fprintf(stderr, "Dumping default XML effect config file.\n");
+ const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);
+ switch (opt) {
+ case 'l': { // -l or --legacy
+ printf("Dumping legacy effect config file\n");
+ if (EffectLoadEffectConfig() < 0) {
+ fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
+ return 1;
+ }
+ return EffectDumpEffects(STDOUT_FILENO);
}
- } else {
- fprintf(stderr, "Invalid arguments.\n"
- "Usage: %s [--legacy|--xml [FILE]]\n", argv[0]);
- return 1;
- }
-
- if (!legacyFormat) {
- ssize_t ret = EffectLoadXmlEffectConfig(path);
- if (ret < 0) {
- fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
- return 2;
+ case 'x': { // -x or --xml
+ printf("Dumping effect config file: %s\n", (optarg == NULL) ? "default" : optarg);
+ ssize_t ret = EffectLoadXmlEffectConfig(optarg);
+ if (ret < 0) {
+ fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
+ return 1;
+ }
+ if (ret > 0) {
+ printf("Partially failed to load config. Skipped %zu elements.\n",
+ (size_t)ret);
+ }
+ return EffectDumpEffects(STDOUT_FILENO);
}
- if (ret > 0) {
- fprintf(stderr, "Partially failed to load config. Skipped %zu elements, "
- "see logcat for detail.\n", (size_t)ret);
+ case 'h': // -h or --help
+ default: {
+ printf("Usage: %s\n"
+ "--legacy (or -l): Legacy audio effect config file to load\n"
+ "--xml (or -x) <FILE>: Audio effect config file to load\n"
+ "--help (or -h): Show this help\n",
+ argv[0]);
+ return 0;
}
}
-
- if (legacyFormat) {
- auto ret = EffectLoadEffectConfig();
- if (ret < 0) {
- fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
- return 3;
- }
- fprintf(stderr, "legacy loadEffectConfig has probably succeed, see logcat to make sure.\n");
- }
-
- if (EffectDumpEffects(STDOUT_FILENO) != 0) {
- fprintf(stderr, "Effect dump failed, see logcat for detail.\n");
- return 4;
- }
}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index 4eea04f..bfc5059 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 @@
* 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 */
}
/*
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index d026e2b..0db7a73 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -15,9 +15,11 @@
*/
#include <cstddef>
+#include <cstdio>
#define LOG_TAG "BundleContext"
#include <android-base/logging.h>
+#include <audio_utils/power.h>
#include <Utils.h>
#include "BundleContext.h"
@@ -34,7 +36,7 @@
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
@@ -212,7 +214,7 @@
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;
@@ -221,8 +223,8 @@
// 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 =
@@ -244,7 +246,7 @@
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;
@@ -397,15 +399,10 @@
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 +410,12 @@
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;
{
@@ -441,8 +439,8 @@
std::vector<Equalizer::BandLevel> 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<int32_t>(i), lvm::kSoftPresets[presetIdx][i]});
+ bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i),
+ lvm::kSoftPresets[presetIdx][i] * 100});
}
RetCode ret = updateControlParameter(bandLevels);
@@ -472,7 +470,8 @@
std::vector<Equalizer::BandLevel> 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<int32_t>(i), mBandGaindB[i]});
+ bandLevels.emplace_back(
+ Equalizer::BandLevel{static_cast<int32_t>(i), mBandGainMdB[i]});
}
return bandLevels;
}
@@ -506,7 +505,7 @@
RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
"indexOutOfRange");
- std::array<int, lvm::MAX_NUM_BANDS> tempLevel;
+ std::array<int, lvm::MAX_NUM_BANDS> tempLevel(mBandGainMdB);
for (const auto& it : bandLevels) {
tempLevel[it.index] = it.levelMb;
}
@@ -520,14 +519,16 @@
for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
- params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+ params.pEQNB_BandDefinition[i].Gain =
+ tempLevel[i] > 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(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
+ mBandGainMdB = tempLevel;
+ LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainMdB)
+ << "mdB";
return RetCode::SUCCESS;
}
@@ -551,18 +552,18 @@
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 47d5e5a..62bb6e4 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -80,8 +80,8 @@
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; }
@@ -135,20 +135,20 @@
int mBassStrengthSaved = 0;
// Equalizer
int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
- std::array<int, lvm::MAX_NUM_BANDS> mBandGaindB;
+ std::array<int, lvm::MAX_NUM_BANDS> mBandGainMdB; /* band gain in millibels */
// Virtualizer
int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
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<Equalizer::BandLevel>& bandLevels);
bool isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel>& bandLevels) const;
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index 3bc889c..143329d 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -73,9 +73,9 @@
MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
MAKE_RANGE(Equalizer, bandLevels,
std::vector<Equalizer::BandLevel>{
- Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+ Equalizer::BandLevel({.index = 0, .levelMb = -1500})},
std::vector<Equalizer::BandLevel>{
- 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),
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index cd9fb60..eb7ab1a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -355,7 +355,7 @@
auto tag = id.get<Volume::Id::commonTag>();
switch (tag) {
case Volume::levelDb: {
- volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+ volParam.set<Volume::levelDb>(static_cast<int>(mContext->getVolumeLevel()));
break;
}
case Volume::mute: {
@@ -384,6 +384,7 @@
if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) {
auto angles = mContext->getSpeakerAngles(id.get<Virtualizer::Id::speakerAnglesPayload>());
+ RETURN_IF(angles.size() == 0, EX_ILLEGAL_ARGUMENT, "getSpeakerAnglesFailed");
Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
specific->set<Parameter::Specific::virtualizer>(param);
return ndk::ScopedAStatus::ok();
diff --git a/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
index e8ac480..e2177db 100644
--- a/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
+++ b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
@@ -31,6 +31,7 @@
(audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
if (effectInterface == nullptr) {
ALOGE("dlsym failed: %s", dlerror());
+ dlclose(effectLib);
exit(-1);
}
symbol = (audio_effect_library_t)(*effectInterface);
diff --git a/media/libeffects/spatializer/tests/SpatializerTest.cpp b/media/libeffects/spatializer/tests/SpatializerTest.cpp
index 110fbb1..3db42b6 100644
--- a/media/libeffects/spatializer/tests/SpatializerTest.cpp
+++ b/media/libeffects/spatializer/tests/SpatializerTest.cpp
@@ -30,6 +30,7 @@
(audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
if (effectInterface == nullptr) {
ALOGE("dlsym failed: %s", dlerror());
+ dlclose(effectLib);
exit(-1);
}
symbol = (audio_effect_library_t)(*effectInterface);
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 64ba977..e33cc0f 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -393,10 +393,6 @@
while (true) {
// demerit the current encoding for each "special" character found after conversion.
// The amount of demerit is somewhat arbitrarily chosen.
- int inchar;
- if (source != sourceLimit) {
- inchar = (source[0] << 8) + source[1];
- }
UChar32 c = ucnv_getNextUChar(conv, &source, sourceLimit, &status);
if (!U_SUCCESS(status)) {
break;
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index a61a1bc..3832e90 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -33,6 +33,7 @@
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 70f8af3..3eee854 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -41,6 +41,7 @@
// keyInputSource: to change audio input source, value is an int in audio_source_t
// (defined in media/mediarecorder.h)
// keyScreenState: either "on" or "off"
+ // keyScreenRotation: one of: 0, 90, 180, 270
static const char * const keyRouting;
static const char * const keySamplingRate;
static const char * const keyFormat;
@@ -48,9 +49,9 @@
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.
+ // 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/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 9e9e9d8..3f08be5 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -388,7 +388,9 @@
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
? asString_VP9Profile(pl.mProfile) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
- ? asString_AV1Profile(pl.mProfile) : "??";
+ ? asString_AV1Profile(pl.mProfile) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)
+ ? asString_DolbyVisionProfile(pl.mProfile) : "??";
const char *niceLevel =
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
? asString_MPEG2Level(pl.mLevel) :
@@ -405,7 +407,9 @@
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
? asString_VP9Level(pl.mLevel) :
mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
- ? asString_AV1Level(pl.mLevel) : "??";
+ ? asString_AV1Level(pl.mLevel) :
+ mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)
+ ? asString_DolbyVisionLevel(pl.mLevel) : "??";
list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
pl.mProfile, pl.mLevel, niceProfile, niceLevel));
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 0365085..cb2007d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1254,10 +1254,6 @@
case OUTPUT_FORMAT_MPEG_4:
case OUTPUT_FORMAT_WEBM:
{
- bool isMPEG4 = true;
- if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
- isMPEG4 = false;
- }
sp<MetaData> meta = new MetaData;
setupMPEG4orWEBMMetaData(&meta);
status = mWriter->start(meta.get());
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e5f2b2b..485923f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2224,6 +2224,11 @@
-ret, strerror(-ret));
return ret;
}
+ if (mVideoDecoder != NULL) {
+ sp<AMessage> params = new AMessage();
+ params->setInt32("android._video-scaling", mode);
+ mVideoDecoder->setParameters(params);
+ }
}
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 8da09c4..f4143da 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -459,6 +459,14 @@
codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
mCodec->setParameters(codecParams);
}
+
+ int32_t videoScalingMode;
+ if (params->findInt32("android._video-scaling", &videoScalingMode)
+ && mCodec != NULL) {
+ sp<AMessage> codecParams = new AMessage();
+ codecParams->setInt32("android._video-scaling", videoScalingMode);
+ mCodec->setParameters(codecParams);
+ }
}
void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 9dae16e..bcb4756 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -157,7 +157,8 @@
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0),
mUseAudioCallback(false),
- mWakeLock(new AWakeLock()) {
+ mWakeLock(new AWakeLock()),
+ mNeedVideoClearAnchor(false) {
CHECK(mediaClock != NULL);
mPlaybackRate = mPlaybackSettings.mSpeed;
mMediaClock->setPlaybackRate(mPlaybackRate);
@@ -234,6 +235,10 @@
return err;
}
}
+
+ if (!mHasAudio && mHasVideo) {
+ mNeedVideoClearAnchor = true;
+ }
mPlaybackSettings = rate;
mPlaybackRate = rate.mSpeed;
mMediaClock->setPlaybackRate(mPlaybackRate);
@@ -327,7 +332,6 @@
mNextVideoTimeMediaUs = -1;
}
- mMediaClock->clearAnchor();
mVideoLateByUs = 0;
mSyncQueues = false;
}
@@ -1371,6 +1375,10 @@
{
Mutex::Autolock autoLock(mLock);
+ if (mNeedVideoClearAnchor && !mHasAudio) {
+ mNeedVideoClearAnchor = false;
+ clearAnchorTime();
+ }
if (mAnchorTimeMediaUs < 0) {
mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
mAnchorTimeMediaUs = mediaTimeUs;
@@ -1525,6 +1533,8 @@
mNextVideoTimeMediaUs + kDefaultVideoFrameIntervalUs);
}
}
+ } else {
+ mHasVideo = false;
}
}
@@ -1686,6 +1696,7 @@
} else {
notifyComplete = mNotifyCompleteVideo;
mNotifyCompleteVideo = false;
+ mHasVideo = false;
}
// If we're currently syncing the queues, i.e. dropping audio while
@@ -1698,7 +1709,17 @@
// is flushed.
syncQueuesDone_l();
}
- clearAnchorTime();
+
+ if (audio && mDrainVideoQueuePending) {
+ // Audio should not clear anchor(MediaClock) directly, because video
+ // postDrainVideoQueue sets msg kWhatDrainVideoQueue into MediaClock
+ // timer, clear anchor without update immediately may block msg posting.
+ // So, postpone clear action to video to ensure anchor can be updated
+ // immediately after clear
+ mNeedVideoClearAnchor = true;
+ } else {
+ clearAnchorTime();
+ }
ALOGV("flushing %s", audio ? "audio" : "video");
if (audio) {
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
index 2ca040f..f0c0a35 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/NuPlayerRenderer.h
@@ -332,6 +332,9 @@
int64_t getDurationUsIfPlayedAtSampleRate(uint32_t numFrames);
DISALLOW_EVIL_CONSTRUCTORS(Renderer);
+
+private:
+ bool mNeedVideoClearAnchor;
};
} // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 505775b..a91b24a 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -293,6 +293,8 @@
}
}
+ void setSurfaceParameters(const sp<AMessage> &msg);
+
private:
// Handles an OMX message. Returns true iff message was handled.
bool onOMXMessage(const sp<AMessage> &msg);
@@ -6511,6 +6513,59 @@
postFillThisBuffer(eligible);
}
+void ACodec::BaseState::setSurfaceParameters(const sp<AMessage> &msg) {
+ sp<AMessage> params;
+ CHECK(msg->findMessage("params", ¶ms));
+
+ status_t err = mCodec->setSurfaceParameters(params);
+ if (err != OK) {
+ ALOGE("[%s] Unable to set input surface parameters (err %d)",
+ mCodec->mComponentName.c_str(),
+ err);
+ return;
+ }
+
+ int64_t timeOffsetUs;
+ if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
+ params->removeEntryAt(params->findEntryByName(PARAMETER_KEY_OFFSET_TIME));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+
+ int64_t skipFramesBeforeUs;
+ if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
+ params->removeEntryAt(params->findEntryByName("skip-frames-before"));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+
+ int32_t dropInputFrames;
+ if (params->findInt32(PARAMETER_KEY_SUSPEND, &dropInputFrames)) {
+ params->removeEntryAt(params->findEntryByName(PARAMETER_KEY_SUSPEND));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+
+ int64_t stopTimeUs;
+ if (params->findInt64("stop-time-us", &stopTimeUs)) {
+ params->removeEntryAt(params->findEntryByName("stop-time-us"));
+
+ if (params->countEntries() == 0) {
+ msg->removeEntryAt(msg->findEntryByName("params"));
+ return;
+ }
+ }
+}
+
bool ACodec::BaseState::onOMXFillBufferDone(
IOMX::buffer_id bufferID,
size_t rangeOffset, size_t rangeLength,
@@ -7411,6 +7466,13 @@
bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetParameters:
+ {
+ BaseState::setSurfaceParameters(msg);
+ if (msg->countEntries() > 0) {
+ mCodec->deferMessage(msg);
+ }
+ return true;
+ }
case kWhatShutdown:
{
mCodec->deferMessage(msg);
@@ -7487,6 +7549,13 @@
bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetParameters:
+ {
+ BaseState::setSurfaceParameters(msg);
+ if (msg->countEntries() > 0) {
+ mCodec->deferMessage(msg);
+ }
+ return true;
+ }
case kWhatShutdown:
{
mCodec->deferMessage(msg);
@@ -7766,27 +7835,7 @@
return handled;
}
-status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
- int32_t videoBitrate;
- if (params->findInt32("video-bitrate", &videoBitrate)) {
- OMX_VIDEO_CONFIG_BITRATETYPE configParams;
- InitOMXParams(&configParams);
- configParams.nPortIndex = kPortIndexOutput;
- configParams.nEncodeBitrate = videoBitrate;
-
- status_t err = mOMXNode->setConfig(
- OMX_IndexConfigVideoBitrate,
- &configParams,
- sizeof(configParams));
-
- if (err != OK) {
- ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
- videoBitrate, err);
-
- return err;
- }
- }
-
+status_t ACodec::setSurfaceParameters(const sp<AMessage> ¶ms) {
int64_t timeOffsetUs;
if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
if (mGraphicBufferSource == NULL) {
@@ -7874,9 +7923,41 @@
mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs);
}
+ return OK;
+}
+
+status_t ACodec::setParameters(const sp<AMessage> ¶ms) {
+ status_t err;
+
+ int32_t videoBitrate;
+ if (params->findInt32("video-bitrate", &videoBitrate)) {
+ OMX_VIDEO_CONFIG_BITRATETYPE configParams;
+ InitOMXParams(&configParams);
+ configParams.nPortIndex = kPortIndexOutput;
+ configParams.nEncodeBitrate = videoBitrate;
+
+ err = mOMXNode->setConfig(
+ OMX_IndexConfigVideoBitrate,
+ &configParams,
+ sizeof(configParams));
+
+ if (err != OK) {
+ ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
+ videoBitrate, err);
+
+ return err;
+ }
+ }
+
+ err = setSurfaceParameters(params);
+ if (err != OK) {
+ ALOGE("Failed to set input surface parameters (err %d)", err);
+ return err;
+ }
+
int32_t tmp;
if (params->findInt32("request-sync", &tmp)) {
- status_t err = requestIDRFrame();
+ err = requestIDRFrame();
if (err != OK) {
ALOGE("Requesting a sync frame failed w/ err %d", err);
@@ -7891,7 +7972,7 @@
rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
}
if (rateFloat > 0) {
- status_t err = setOperatingRate(rateFloat, mIsVideo);
+ err = setOperatingRate(rateFloat, mIsVideo);
if (err != OK) {
ALOGI("Failed to set parameter 'operating-rate' (err %d)", err);
}
@@ -7900,7 +7981,7 @@
int32_t intraRefreshPeriod = 0;
if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
&& intraRefreshPeriod > 0) {
- status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
+ err = setIntraRefreshPeriod(intraRefreshPeriod, false);
if (err != OK) {
ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
mComponentName.c_str());
@@ -7910,7 +7991,7 @@
int32_t lowLatency = 0;
if (params->findInt32("low-latency", &lowLatency)) {
- status_t err = setLowLatency(lowLatency);
+ err = setLowLatency(lowLatency);
if (err != OK) {
return err;
}
@@ -7918,7 +7999,7 @@
int32_t latency = 0;
if (params->findInt32("latency", &latency) && latency > 0) {
- status_t err = setLatency(latency);
+ err = setLatency(latency);
if (err != OK) {
ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
mComponentName.c_str());
@@ -7930,7 +8011,7 @@
if (params->findInt32("audio-presentation-presentation-id", &presentationId)) {
int32_t programId = -1;
params->findInt32("audio-presentation-program-id", &programId);
- status_t err = setAudioPresentation(presentationId, programId);
+ err = setAudioPresentation(presentationId, programId);
if (err != OK) {
ALOGI("[%s] failed setAudioPresentation. Failure is fine since this key is optional",
mComponentName.c_str());
@@ -8003,7 +8084,7 @@
{
int32_t tunnelPeek = 0;
if (params->findInt32(TUNNEL_PEEK_KEY, &tunnelPeek)) {
- status_t err = setTunnelPeek(tunnelPeek);
+ err = setTunnelPeek(tunnelPeek);
if (err != OK) {
return err;
}
@@ -8012,7 +8093,7 @@
{
int32_t tunnelPeekSetLegacy = 0;
if (params->findInt32(TUNNEL_PEEK_SET_LEGACY_KEY, &tunnelPeekSetLegacy)) {
- status_t err = setTunnelPeekLegacy(tunnelPeekSetLegacy);
+ err = setTunnelPeekLegacy(tunnelPeekSetLegacy);
if (err != OK) {
return err;
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index b84dc27..2cd3768 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -31,7 +31,6 @@
#include <utils/Log.h>
#include <functional>
-#include <fcntl.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -564,6 +563,10 @@
mResetStatus = OK;
mPreAllocFirstTime = true;
mPrevAllTracksTotalMetaDataSizeEstimate = 0;
+ mIsFirstChunk = false;
+ mDone = false;
+ mThread = 0;
+ mDriftTimeUs = 0;
// Following variables only need to be set for the first recording session.
// And they will stay the same for all the recording sessions.
diff --git a/media/libstagefright/VideoFrameSchedulerBase.cpp b/media/libstagefright/VideoFrameSchedulerBase.cpp
index 0d1517b..965014c 100644
--- a/media/libstagefright/VideoFrameSchedulerBase.cpp
+++ b/media/libstagefright/VideoFrameSchedulerBase.cpp
@@ -451,7 +451,7 @@
return origRenderTime;
}
- ATRACE_INT("FRAME_VSYNCS", vsyncsForLastFrame);
+ ATRACE_INT64("FRAME_VSYNCS", vsyncsForLastFrame);
}
mLastVsyncTime = nextVsyncTime;
}
@@ -460,7 +460,7 @@
renderTime -= (renderTime - mVsyncTime) % mVsyncPeriod;
renderTime += mVsyncPeriod / 2;
ALOGV("adjusting render: %lld => %lld", (long long)origRenderTime, (long long)renderTime);
- ATRACE_INT("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
+ ATRACE_INT64("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
return renderTime;
}
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index d3fd790..665ceee 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -340,8 +340,8 @@
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="8x8" />
<Limit name="block-count" range="1-4096" /> <!-- max 512x512 -->
- <Limit name="blocks-per-second" range="1-122880" />
- <Limit name="frame-rate" range="1-120" />
+ <Limit name="blocks-per-second" range="1-259200" />
+ <Limit name="frame-rate" range="1-300" />
<Limit name="bitrate" range="1-10000000" />
<Limit name="complexity" range="0-10" default="0" />
<Limit name="quality" range="0-100" default="80" />
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 08c7917..e535d5d 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -603,6 +603,7 @@
status_t internalError = UNKNOWN_ERROR);
status_t requestIDRFrame();
+ status_t setSurfaceParameters(const sp<AMessage> ¶ms);
status_t setParameters(const sp<AMessage> ¶ms);
// set vendor extension parameters specified in params that are supported by the codec
diff --git a/media/libstagefright/tests/HEVC/AndroidTest.xml b/media/libstagefright/tests/HEVC/AndroidTest.xml
index ff850a2..00bb3e5 100644
--- a/media/libstagefright/tests/HEVC/AndroidTest.xml
+++ b/media/libstagefright/tests/HEVC/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push" value="HEVCUtilsUnitTest->/data/local/tmp/HEVCUtilsUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest.zip?unzip=true"
- value="/data/local/tmp/HEVCUtilsUnitTest/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="HEVCUtilsUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="HEVCUtilsUnitTest-1.0" />
+ <option name="dynamic-config-module" value="HEVCUtilsUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="HEVCUtilsUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/HEVCUtilsUnitTest/" />
+ <option name="native-test-flag" value="-P /sdcard/tests/HEVCUtilsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/libstagefright/tests/HEVC/DynamicConfig.xml b/media/libstagefright/tests/HEVC/DynamicConfig.xml
new file mode 100644
index 0000000..517449c
--- /dev/null
+++ b/media/libstagefright/tests/HEVC/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/tests/extractorFactory/AndroidTest.xml b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
index 3aa6392..f1d4201 100644
--- a/media/libstagefright/tests/extractorFactory/AndroidTest.xml
+++ b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ExtractorFactoryTest->/data/local/tmp/ExtractorFactoryTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
- value="/data/local/tmp/ExtractorFactoryTestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ExtractorFactoryTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="extractor-1.5" />
+ <option name="dynamic-config-module" value="ExtractorFactoryTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ExtractorFactoryTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/ExtractorFactoryTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/extractor-1.5/" />
</test>
</configuration>
diff --git a/media/libstagefright/tests/extractorFactory/DynamicConfig.xml b/media/libstagefright/tests/extractorFactory/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/tests/writer/AndroidTest.xml b/media/libstagefright/tests/writer/AndroidTest.xml
index cc890fe..0b0eb01 100644
--- a/media/libstagefright/tests/writer/AndroidTest.xml
+++ b/media/libstagefright/tests/writer/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="writerTest->/data/local/tmp/writerTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/WriterTestRes-1.1.zip?unzip=true"
- value="/data/local/tmp/WriterTestRes/" />
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="writerTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="WriterTestRes-1.2" />
+ <option name="dynamic-config-module" value="writerTest" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="writerTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/WriterTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/WriterTestRes-1.2/" />
<option name="native-test-flag" value="-C true" />
</test>
</configuration>
diff --git a/media/libstagefright/tests/writer/DynamicConfig.xml b/media/libstagefright/tests/writer/DynamicConfig.xml
new file mode 100644
index 0000000..e6dc502
--- /dev/null
+++ b/media/libstagefright/tests/writer/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/WriterTestRes-1.2.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/timedtext/test/AndroidTest.xml b/media/libstagefright/timedtext/test/AndroidTest.xml
index 3654e23..0d5d79f 100644
--- a/media/libstagefright/timedtext/test/AndroidTest.xml
+++ b/media/libstagefright/timedtext/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="TimedTextUnitTest->/data/local/tmp/TimedTextUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest.zip?unzip=true"
- value="/data/local/tmp/TimedTextUnitTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="TimedTextUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="TimedTextUnitTest-1.0" />
+ <option name="dynamic-config-module" value="TimedTextUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="TimedTextUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTestRes/" />
+ <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/libstagefright/timedtext/test/DynamicConfig.xml b/media/libstagefright/timedtext/test/DynamicConfig.xml
new file mode 100644
index 0000000..e36277e
--- /dev/null
+++ b/media/libstagefright/timedtext/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/timedtext/test/fuzzer/Android.bp b/media/libstagefright/timedtext/test/fuzzer/Android.bp
new file mode 100644
index 0000000..6590ebb
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/Android.bp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_library_static {
+ name: "timedtext_fuzz-protos",
+
+ srcs: ["timedtext_fuzz.proto"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: ["libprotobuf-cpp-full"],
+ proto: {
+ type: "full",
+ canonical_path_from_root: false,
+ local_include_dirs: ["."],
+ export_proto_headers: true,
+ },
+}
+
+cc_fuzz {
+ name: "timedtext_fuzzer",
+ srcs: [
+ "timedtext_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libstagefright_timedtext",
+ "timedtext_fuzz-protos",
+ ],
+ shared_libs: [
+ "libstagefright_foundation",
+ "libprotobuf-cpp-full",
+ "libbinder",
+ "libprotobuf-mutator",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/media/libstagefright/timedtext/test/fuzzer/README.md b/media/libstagefright/timedtext/test/fuzzer/README.md
new file mode 100644
index 0000000..f391ea7
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/README.md
@@ -0,0 +1,23 @@
+# Fuzzer for libstagefright_timedtext
+
+libstagefright_timedtext supports the following parameters:
+1. Flags (parameter name: `flags`)
+2. TimeMs (parameter name: `timeMs`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `flags` | 1. `TextDescriptions::OUT_OF_BAND_TEXT_SRT` 2. `TextDescriptions::GLOBAL_DESCRIPTIONS` 3. `TextDescriptions::IN_BAND_TEXT_3GPP` 4. `TextDescriptions::LOCAL_DESCRIPTIONS` | Value chosen from valid values by obtaining index from FuzzedDataProvider|
+| `timeMs` | `INT_MIN` to `INT_MAX` | Value obtained from FuzzedDataProvider|
+
+
+#### Steps to run
+
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) timedtext_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/timedtext_fuzzer/timedtext_fuzzer
+```
diff --git a/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto
new file mode 100644
index 0000000..4c90278
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * proto files are used for Structure Aware fuzzing so that fuzzing can be
+ * made more effective.
+ * timedtext_fuzz.proto is used to declare structures, which are used
+ * purely inside timedtext_fuzzer.
+ */
+
+syntax = "proto3";
+
+enum Flag {
+ flag3gppglobal = 0;
+ flag3gpplocal = 1;
+ flagsrtlocal = 2;
+}
+
+enum ChunkType {
+ default = 0;
+ tx3g = 1954034535;
+ styl = 1937013100;
+ krok = 1802661739;
+ hlit = 1751935348;
+ hclr = 1751346290;
+ dlay = 1684824441;
+ href = 1752327526;
+ tbox = 1952608120;
+ blnk = 1651273323;
+ txrp = 1953985136;
+}
+
+message FontRecord {
+ uint32 fontId = 1;
+ repeated uint32 font = 2;
+}
+
+message SRTLocal {
+ repeated uint32 data = 1;
+}
+
+message GPPGlobal {
+ uint64 reservedBytes = 1;
+ uint32 displayFlags = 2;
+ int32 horizontal_vertical_justification = 3;
+ uint32 rgba = 4;
+ int32 textBox = 5;
+ uint32 styleRecordStart = 6;
+ uint32 fontId = 7;
+ uint32 fontStyle = 8;
+ uint32 entryCount = 9;
+ repeated FontRecord fontEntry = 10;
+ uint32 defaultDisparity = 11;
+}
+
+message StyleRecord {
+ uint32 startchar = 1;
+ uint32 font = 2;
+ uint32 rgba = 3;
+}
+
+message TextStyleBox {
+ uint32 count = 1;
+ repeated StyleRecord record = 2;
+}
+
+message HighlightBox {
+ uint32 start = 1;
+ uint32 end = 2;
+}
+
+message HighlightColor {
+ uint32 rgba = 1;
+}
+
+message TextKaraokeBox {
+ uint32 highlightStartTime = 1;
+ uint32 entryCount = 2;
+ repeated uint64 highlightData = 3;
+}
+
+message BoxRecord {
+ uint32 topleft = 1;
+ uint32 bottomright = 2;
+}
+
+message BlinkBox {
+ uint32 charoffset = 1;
+}
+
+message HyperTextBox {
+ uint32 charoffset = 1;
+ uint32 urlLength = 2;
+ repeated uint32 url = 3;
+ uint32 altLength = 4;
+ repeated uint32 altString = 5;
+}
+
+message GPPLocalText {
+ string text = 1;
+}
+
+message GPPLocalFormat {
+ uint64 reservedBytes = 1;
+ oneof formatStyle {
+ TextStyleBox textbox = 2;
+ HighlightBox hltbox = 3;
+ HighlightColor hltcolor = 4;
+ TextKaraokeBox krokbox = 5;
+ uint32 scrollDelay = 6;
+ HyperTextBox hrefBox = 7;
+ BoxRecord boxrecord = 8;
+ BlinkBox blinkBox = 9;
+ uint32 wrapFlag = 10;
+ }
+}
+
+message GPPLocal {
+ GPPLocalText localtext = 1;
+ GPPLocalFormat format = 2;
+}
+
+message TimedText {
+ Flag handle = 1;
+ int32 timeMs = 2;
+ SRTLocal srt = 3;
+ GPPGlobal global = 4;
+ GPPLocal local = 5;
+}
diff --git a/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp
new file mode 100644
index 0000000..da1bdf8
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/Parcel.h>
+#include <timedtext/TextDescriptions.h>
+#include <timedtext_fuzz.pb.h>
+#include "fuzzer/FuzzedDataProvider.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+using namespace android;
+constexpr int32_t kTextBytes = 2;
+constexpr int32_t kChunkBytes = 8;
+constexpr int32_t kChunkTypeBytes = 4;
+constexpr int32_t kGlobalTextOffset = 0;
+constexpr size_t kByte3Mask = 0xff000000UL;
+constexpr size_t kByte2Mask = 0x00ff0000UL;
+constexpr size_t kByte1Mask = 0x0000ff00UL;
+constexpr size_t kByte0Mask = 0x000000ffUL;
+
+/**
+ * Sets ChunkSize/ChunkType (uint32_t) in timedtext-description vector<uint8_t>
+ * by extracting each byte from ChunkSize and populating the vector.
+ */
+void setChunkParameter(std::vector<uint8_t>& timedtext, size_t param, size_t paramOffset) {
+ timedtext[paramOffset + 0] = (param & kByte3Mask) >> 24;
+ timedtext[paramOffset + 1] = (param & kByte2Mask) >> 16;
+ timedtext[paramOffset + 2] = (param & kByte1Mask) >> 8;
+ timedtext[paramOffset + 3] = (param & kByte0Mask);
+}
+
+/**
+ * Sets TextLength(uint16_t) in 3GPPLocal-description vector<uint8_t>
+ * by extracting each byte from TextLength and populating the vector.
+ */
+void setTextSize(std::vector<uint8_t>& local3GPPDescription, int32_t textLength) {
+ local3GPPDescription[0] = (textLength & kByte1Mask) >> 8;
+ local3GPPDescription[1] = (textLength & kByte0Mask);
+}
+
+DEFINE_PROTO_FUZZER(const TimedText& input) {
+ switch (input.handle()) {
+ case flag3gppglobal: {
+ size_t gppGlobalByteSize = input.global().ByteSizeLong();
+ if (gppGlobalByteSize) {
+ std::vector<uint8_t> global3GPPDescription(gppGlobalByteSize + kChunkBytes);
+ setChunkParameter(global3GPPDescription, gppGlobalByteSize, kGlobalTextOffset);
+ setChunkParameter(global3GPPDescription, tx3g, kGlobalTextOffset + kChunkTypeBytes);
+ input.global().SerializeToArray(global3GPPDescription.data() + kChunkBytes,
+ global3GPPDescription.size());
+ Parcel* parcel = new Parcel();
+ TextDescriptions::getParcelOfDescriptions(
+ global3GPPDescription.data(), global3GPPDescription.size(),
+ TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::GLOBAL_DESCRIPTIONS,
+ input.timems(), parcel);
+ delete parcel;
+ }
+ break;
+ }
+ case flag3gpplocal: {
+ size_t gppLocalByteSize = input.local().ByteSizeLong();
+ if (gppLocalByteSize) {
+ std::vector<uint8_t> local3GPPDescription(gppLocalByteSize + kChunkBytes +
+ kTextBytes);
+ std::string text = input.local().localtext().text();
+ int32_t textLength = text.size();
+ setTextSize(local3GPPDescription, textLength);
+ input.local().localtext().SerializeToArray(local3GPPDescription.data() + kTextBytes,
+ textLength);
+ size_t gppLocalFormatSize = input.local().format().ByteSizeLong();
+ size_t textOffset = textLength + kTextBytes;
+ setChunkParameter(local3GPPDescription, gppLocalFormatSize, textOffset);
+ switch (input.local().format().formatStyle_case()) {
+ case GPPLocalFormat::FormatStyleCase::kTextbox: {
+ setChunkParameter(local3GPPDescription, styl, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kHltbox: {
+ setChunkParameter(local3GPPDescription, hlit, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kHltcolor: {
+ setChunkParameter(local3GPPDescription, hclr, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kKrokbox: {
+ setChunkParameter(local3GPPDescription, krok, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kScrollDelay: {
+ setChunkParameter(local3GPPDescription, dlay, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kHrefBox: {
+ setChunkParameter(local3GPPDescription, href, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kBoxrecord: {
+ setChunkParameter(local3GPPDescription, tbox, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kBlinkBox: {
+ setChunkParameter(local3GPPDescription, blnk, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ case GPPLocalFormat::FormatStyleCase::kWrapFlag: {
+ setChunkParameter(local3GPPDescription, txrp, textOffset + kChunkTypeBytes);
+ input.local().format().SerializeToArray(
+ local3GPPDescription.data() + textOffset + kChunkBytes,
+ gppLocalFormatSize);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ Parcel* parcel = new Parcel();
+ TextDescriptions::getParcelOfDescriptions(
+ local3GPPDescription.data(), local3GPPDescription.size(),
+ TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::LOCAL_DESCRIPTIONS,
+ input.timems(), parcel);
+ delete parcel;
+ }
+ break;
+ }
+ case flagsrtlocal: {
+ size_t srtByteSize = input.srt().ByteSizeLong();
+ if (srtByteSize) {
+ std::vector<uint8_t> srtLocalDescription(srtByteSize);
+ input.srt().SerializeToArray(srtLocalDescription.data(),
+ srtLocalDescription.size());
+ Parcel* parcel = new Parcel();
+ TextDescriptions::getParcelOfDescriptions(
+ srtLocalDescription.data(), srtLocalDescription.size(),
+ TextDescriptions::OUT_OF_BAND_TEXT_SRT |
+ TextDescriptions::LOCAL_DESCRIPTIONS,
+ input.timems(), parcel);
+ delete parcel;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index afc873c..2f204f9 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -55,4 +55,5 @@
name: "media_codecs",
srcs: ["media_codecs.xsd"],
package_name: "media.codecs",
+ root_elements: ["MediaCodecs"],
}
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index 95c347a..7de5955 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -171,7 +171,6 @@
public class XmlParser {
ctor public XmlParser();
- method public static media.codecs.Included readIncluded(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static media.codecs.MediaCodecs readMediaCodecs(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/media/module/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
index 3202cc5..4bb2215 100644
--- a/media/module/bqhelper/GraphicBufferSource.cpp
+++ b/media/module/bqhelper/GraphicBufferSource.cpp
@@ -589,7 +589,7 @@
void GraphicBufferSource::onDataspaceChanged_l(
android_dataspace dataspace, android_pixel_format pixelFormat) {
- ALOGD("got buffer with new dataSpace #%x", dataspace);
+ ALOGD("got buffer with new dataSpace %#x", dataspace);
mLastDataspace = dataspace;
if (ColorUtils::convertDataSpaceToV0(dataspace)) {
diff --git a/media/module/codecs/amrnb/dec/test/AndroidTest.xml b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
index 1a9e678..539fa5c 100644
--- a/media/module/codecs/amrnb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
@@ -13,19 +13,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for Amr-nb Decoder unit test">
+<configuration description="Test module config for Amr-wb Decoder unit test">
<option name="test-suite-tag" value="AmrnbDecoderTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrnbDecoderTest->/data/local/tmp/AmrnbDecoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrnbDecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrnbDecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrnbDecoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrnbDecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrnbDecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrnbDecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrnbDecoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrnb/dec/test/DynamicConfig.xml b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..de81c48
--- /dev/null
+++ b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrnb/enc/test/AndroidTest.xml b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
index 9fe61b1..1509728 100644
--- a/media/module/codecs/amrnb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
@@ -13,19 +13,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Test module config for Amr-nb Encoder unit test">
+<configuration description="Test module config for Amr-wb Encoder unit test">
<option name="test-suite-tag" value="AmrnbEncoderTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrnbEncoderTest->/data/local/tmp/AmrnbEncoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrnbEncoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrnbEncoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrnbEncoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrnbEncoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrnbEncoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrnbEncoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrnbEncoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrnb/enc/test/DynamicConfig.xml b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..b22df38
--- /dev/null
+++ b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrwb/dec/test/AndroidTest.xml b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
index e211a1f..392df03 100644
--- a/media/module/codecs/amrwb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrwbDecoderTest->/data/local/tmp/AmrwbDecoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrwbDecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrwbDecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrwbDecoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrwbDecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrwbDecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrwbDecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrwbDecoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrwb/dec/test/DynamicConfig.xml b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..d41517f
--- /dev/null
+++ b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrwb/enc/test/AndroidTest.xml b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
index 46f147c..8822cb2 100644
--- a/media/module/codecs/amrwb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="AmrwbEncoderTest->/data/local/tmp/AmrwbEncoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true"
- value="/data/local/tmp/AmrwbEncoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AmrwbEncoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AmrwbEncoderTest-1.0" />
+ <option name="dynamic-config-module" value="AmrwbEncoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AmrwbEncoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AmrwbEncoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AmrwbEncoderTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/codecs/amrwb/enc/test/DynamicConfig.xml b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..1cf5bf5
--- /dev/null
+++ b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/flac/dec/test/AndroidTest.xml b/media/module/codecs/flac/dec/test/AndroidTest.xml
index bebba8e..015f728 100644
--- a/media/module/codecs/flac/dec/test/AndroidTest.xml
+++ b/media/module/codecs/flac/dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
- value="/data/local/tmp/FlacDecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="FlacDecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="FlacDecoder-1.0" />
+ <option name="dynamic-config-module" value="FlacDecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="FlacDecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/FlacDecoder-1.0/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/codecs/flac/dec/test/DynamicConfig.xml b/media/module/codecs/flac/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/module/codecs/flac/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
index 8bb4d1c..bd620d6 100755
--- a/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
+++ b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
@@ -19,14 +19,22 @@
<option name="cleanup" value="true" />
<option name="push" value="Mpeg4H263DecoderTest->/data/local/tmp/Mpeg4H263DecoderTest" />
<option name="append-bitness" value="true" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true"
- value="/data/local/tmp/Mpeg4H263DecoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mpeg4H263DecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mpeg4H263DecoderTest-1.2" />
+ <option name="dynamic-config-module" value="Mpeg4H263DecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mpeg4H263DecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263DecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mpeg4H263DecoderTest-1.2/" />
</test>
</configuration>
diff --git a/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml b/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..5219361
--- /dev/null
+++ b/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.2.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
index 5218932..6b352b0 100644
--- a/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
+++ b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
- value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mpeg4H263EncoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mpeg4H263Encoder-1.1" />
+ <option name="dynamic-config-module" value="Mpeg4H263EncoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mpeg4H263EncoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mpeg4H263Encoder-1.1/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml b/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..ceb33ef
--- /dev/null
+++ b/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder-1.1.zip
+ </value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/mp3dec/test/AndroidTest.xml b/media/module/codecs/mp3dec/test/AndroidTest.xml
index 29952eb..d16f152 100644
--- a/media/module/codecs/mp3dec/test/AndroidTest.xml
+++ b/media/module/codecs/mp3dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="Mp3DecoderTest->/data/local/tmp/Mp3DecoderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true"
- value="/data/local/tmp/Mp3DecoderTestRes/" />
+</target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mp3DecoderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mp3DecoderTest-1.3" />
+ <option name="dynamic-config-module" value="Mp3DecoderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mp3DecoderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mp3DecoderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mp3DecoderTest-1.3/" />
</test>
</configuration>
diff --git a/media/module/codecs/mp3dec/test/DynamicConfig.xml b/media/module/codecs/mp3dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..048940b
--- /dev/null
+++ b/media/module/codecs/mp3dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.3.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/esds/tests/AndroidTest.xml b/media/module/esds/tests/AndroidTest.xml
index a4fbc7f..87ca58c 100644
--- a/media/module/esds/tests/AndroidTest.xml
+++ b/media/module/esds/tests/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ESDSTest->/data/local/tmp/ESDSTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/ESDS/ESDSTestRes-1.0.zip?unzip=true"
- value="/data/local/tmp/ESDSTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ESDSTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="ESDSTestRes-1.1" />
+ <option name="dynamic-config-module" value="ESDSTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ESDSTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/ESDSTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/ESDSTestRes-1.1/" />
</test>
</configuration>
diff --git a/media/module/esds/tests/DynamicConfig.xml b/media/module/esds/tests/DynamicConfig.xml
new file mode 100644
index 0000000..9718dda
--- /dev/null
+++ b/media/module/esds/tests/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/ESDS/ESDSTestRes-1.1.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/extractors/mkv/MatroskaExtractor.cpp b/media/module/extractors/mkv/MatroskaExtractor.cpp
index 2b72387..6900341 100644
--- a/media/module/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/module/extractors/mkv/MatroskaExtractor.cpp
@@ -1800,7 +1800,6 @@
int32_t isotransfer = 2; // ISO unspecified
int32_t coeffs = 2; // ISO unspecified
bool fullRange = false; // default
- bool rangeSpecified = false;
if (isValidInt32ColourValue(color->primaries)) {
primaries = color->primaries;
@@ -1816,7 +1815,6 @@
// We only support MKV broadcast range (== limited) and full range.
// We treat all other value as the default limited range.
fullRange = color->range == 2 /* MKV fullRange */;
- rangeSpecified = true;
}
int32_t range = 0;
diff --git a/media/module/extractors/mp3/VBRISeeker.cpp b/media/module/extractors/mp3/VBRISeeker.cpp
index ca51b88..a50754b 100644
--- a/media/module/extractors/mp3/VBRISeeker.cpp
+++ b/media/module/extractors/mp3/VBRISeeker.cpp
@@ -84,7 +84,7 @@
scale,
entrySize);
- if (entrySize > 4) {
+ if (entrySize < 1 || entrySize > 4) {
ALOGE("invalid VBRI entry size: %zu", entrySize);
return NULL;
}
@@ -122,16 +122,13 @@
off64_t offset = post_id3_pos;
for (size_t i = 0; i < numEntries; ++i) {
- uint32_t numBytes;
+ uint32_t numBytes = 0;
+ // entrySize is known to be [1..4]
switch (entrySize) {
case 1: numBytes = buffer[i]; break;
case 2: numBytes = U16_AT(buffer + 2 * i); break;
case 3: numBytes = U24_AT(buffer + 3 * i); break;
- default:
- {
- CHECK_EQ(entrySize, 4u);
- numBytes = U32_AT(buffer + 4 * i); break;
- }
+ case 4: numBytes = U32_AT(buffer + 4 * i); break;
}
numBytes *= scale;
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 1d88785..38cf29d 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -26,7 +26,6 @@
#include <stdlib.h>
#include <string.h>
-#include <log/log.h>
#include <utils/Log.h>
#include "AC4Parser.h"
@@ -6501,6 +6500,16 @@
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
+ void *presentationsData;
+ size_t presentationsSize;
+ if (AMediaFormat_getBuffer(
+ mFormat, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+ &presentationsData, &presentationsSize)) {
+ AMediaFormat_setBuffer(
+ meta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+ presentationsData, presentationsSize);
+ }
+
++mCurrentSampleIndex;
*out = mBuffer;
diff --git a/media/module/extractors/tests/AndroidTest.xml b/media/module/extractors/tests/AndroidTest.xml
index fc8152c..22669df 100644
--- a/media/module/extractors/tests/AndroidTest.xml
+++ b/media/module/extractors/tests/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ExtractorUnitTest->/data/local/tmp/ExtractorUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true"
- value="/data/local/tmp/ExtractorUnitTestRes/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ExtractorUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="extractor-1.5" />
+ <option name="dynamic-config-module" value="ExtractorUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ExtractorUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/ExtractorUnitTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/extractor-1.5/" />
</test>
</configuration>
diff --git a/media/module/extractors/tests/DynamicConfig.xml b/media/module/extractors/tests/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/module/extractors/tests/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/foundation/tests/AVCUtils/AndroidTest.xml b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
index 6a088a8..e30bfbf 100644
--- a/media/module/foundation/tests/AVCUtils/AndroidTest.xml
+++ b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
@@ -18,14 +18,22 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push" value="AVCUtilsUnitTest->/data/local/tmp/AVCUtilsUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.zip?unzip=true"
- value="/data/local/tmp/AVCUtilsUnitTest/" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="AVCUtilsUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="AVCUtilsUnitTest-1.0" />
+ <option name="dynamic-config-module" value="AVCUtilsUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="AVCUtilsUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/AVCUtilsUnitTest/" />
+ <option name="native-test-flag" value="-P /sdcard/test/AVCUtilsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/foundation/tests/AVCUtils/DynamicConfig.xml b/media/module/foundation/tests/AVCUtils/DynamicConfig.xml
new file mode 100644
index 0000000..e5b8bad
--- /dev/null
+++ b/media/module/foundation/tests/AVCUtils/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value> https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/foundation/tests/OpusHeader/AndroidTest.xml b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
index afee16a..4aa4cd2 100644
--- a/media/module/foundation/tests/OpusHeader/AndroidTest.xml
+++ b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="OpusHeaderTest->/data/local/tmp/OpusHeaderTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true"
- value="/data/local/tmp/OpusHeaderTestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="OpusHeaderTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="OpusHeader-1.0" />
+ <option name="dynamic-config-module" value="OpusHeaderTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="OpusHeaderTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/OpusHeaderTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/OpusHeader-1.0/" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/foundation/tests/OpusHeader/DynamicConfig.xml b/media/module/foundation/tests/OpusHeader/DynamicConfig.xml
new file mode 100644
index 0000000..ebac328
--- /dev/null
+++ b/media/module/foundation/tests/OpusHeader/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/id3/test/AndroidTest.xml b/media/module/id3/test/AndroidTest.xml
index 50f9253..b169994 100644
--- a/media/module/id3/test/AndroidTest.xml
+++ b/media/module/id3/test/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="ID3Test->/data/local/tmp/ID3Test" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true"
- value="/data/local/tmp/ID3TestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="ID3Test" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="ID3TestRes-1.3" />
+ <option name="dynamic-config-module" value="ID3Test" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="ID3Test" />
- <option name="native-test-flag" value="-P /data/local/tmp/ID3TestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/ID3TestRes-1.3/" />
</test>
</configuration>
diff --git a/media/module/id3/test/DynamicConfig.xml b/media/module/id3/test/DynamicConfig.xml
new file mode 100644
index 0000000..5ae4fcd
--- /dev/null
+++ b/media/module/id3/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.3.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/metadatautils/test/AndroidTest.xml b/media/module/metadatautils/test/AndroidTest.xml
index d6497f3..ce8c4d6 100644
--- a/media/module/metadatautils/test/AndroidTest.xml
+++ b/media/module/metadatautils/test/AndroidTest.xml
@@ -18,13 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="false" />
<option name="push" value="MetaDataUtilsTest->/data/local/tmp/MetaDataUtilsTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/metadatautils/MetaDataUtilsTestRes-1.0.zip?unzip=true"
- value="/data/local/tmp/MetaDataUtilsTestRes/" />
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="MetaDataUtilsTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="MetaDataUtilsTest-1.1" />
+ <option name="dynamic-config-module" value="MetaDataUtilsTest" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="MetaDataUtilsTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/MetaDataUtilsTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/MetaDataUtilsTest-1.1/" />
</test>
</configuration>
diff --git a/media/module/metadatautils/test/DynamicConfig.xml b/media/module/metadatautils/test/DynamicConfig.xml
new file mode 100644
index 0000000..9d80bf3
--- /dev/null
+++ b/media/module/metadatautils/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/metadatautils/MetaDataUtilsTestRes-1.1.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/module/mpeg2ts/test/AndroidTest.xml b/media/module/mpeg2ts/test/AndroidTest.xml
index ac1294d..836c9f8 100644
--- a/media/module/mpeg2ts/test/AndroidTest.xml
+++ b/media/module/mpeg2ts/test/AndroidTest.xml
@@ -18,14 +18,21 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="Mpeg2tsUnitTest->/data/local/tmp/Mpeg2tsUnitTest" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true"
- value="/data/local/tmp/Mpeg2tsUnitTestRes/" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="Mpeg2tsUnitTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="Mpeg2tsUnitTest-1.0" />
+ <option name="dynamic-config-module" value="Mpeg2tsUnitTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="Mpeg2tsUnitTest" />
- <option name="native-test-flag" value="-P /data/local/tmp/Mpeg2tsUnitTestRes/" />
+ <option name="native-test-flag" value="-P /sdcard/test/Mpeg2tsUnitTest-1.0/" />
</test>
</configuration>
diff --git a/media/module/mpeg2ts/test/DynamicConfig.xml b/media/module/mpeg2ts/test/DynamicConfig.xml
new file mode 100644
index 0000000..017a3c6
--- /dev/null
+++ b/media/module/mpeg2ts/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/mtp/OWNERS b/media/mtp/OWNERS
index 54d3d4a..6b5336e 100644
--- a/media/mtp/OWNERS
+++ b/media/mtp/OWNERS
@@ -1,5 +1,9 @@
set noparent
+aprasath@google.com
+anothermark@google.com
+kumarashishg@google.com
+sarup@google.com
jsharkey@android.com
jameswei@google.com
rmojumder@google.com
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
index 011c38c..e2fe177 100644
--- a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
@@ -90,13 +90,13 @@
}
String decoderMime = decoderFormat.getString(MediaFormat.KEY_MIME);
- ArrayList<String> listOfDeocders =
+ ArrayList<String> decoders =
MediaCodecBase.selectCodecs(decoderMime, null, null, false, mIsCodecSoftware);
- if (listOfDeocders.isEmpty()) {
+ if (decoders.isEmpty()) {
Log.e(TAG, "No suitable decoder found for mime: " + decoderMime);
return -1;
}
- mDecoder = MediaCodec.createByCodecName(listOfDeocders.get(0));
+ mDecoder = MediaCodec.createByCodecName(decoders.get(0));
MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat);
ArrayList<String> listOfEncoders =
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
index 1890661..1b66b01 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -14,18 +14,26 @@
limitations under the License.
-->
<configuration description="Runs Media Benchmark Tests">
+ <option name="test-tag" value="MediaBenchmarkTest" />
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push-file"
- key="https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark.zip?unzip=true"
- value="/data/local/tmp/MediaBenchmark/res/" />
</target_preparer>
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="cleanup-apks" value="false" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="host" />
+ <option name="config-filename" value="MediaBenchmarkTest" />
+ <option name="version" value="1.0"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+ <option name="push-all" value="true" />
+ <option name="media-folder-name" value="MediaBenchmarkTest-1.1" />
+ <option name="dynamic-config-module" value="MediaBenchmarkTest" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="MediaBenchmarkTest.apk" />
</target_preparer>
- <option name="test-tag" value="MediaBenchmarkTest" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.media.benchmark" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
new file mode 100644
index 0000000..1278f29
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark-1.1.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
index 24dbccc..2bef254 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
@@ -1,4 +1,4 @@
<resources>
- <string name="input_file_path">/data/local/tmp/MediaBenchmark/res/</string>
+ <string name="input_file_path">/sdcard/test/MediaBenchmarkTest-1.1/</string>
<string name="output_file_path">/data/local/tmp/MediaBenchmark/output/</string>
</resources>
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 663df69..c7de3d2 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -19,7 +19,8 @@
],
}
-tidy_errors = [
+// base tidy_errors for this and all subprojects.
+audioflinger_base_tidy_errors = [
// https://clang.llvm.org/extra/clang-tidy/checks/list.html
// For many categories, the checks are too many to specify individually.
// Feel free to disable as needed - as warnings are generally ignored,
@@ -71,8 +72,10 @@
"-bugprone-suspicious-string-compare",
"-cert-oop54-cpp", // found in TransactionLog.h
"-bugprone-narrowing-conversions", // b/182410845
+]
- // TODO(b/275642749) Reenable these warnings
+// TODO(b/275642749) Reenable these warnings
+audioflinger_tidy_errors = audioflinger_base_tidy_errors + [
"-bugprone-assignment-in-if-condition",
"-bugprone-forward-declaration-namespace",
"-bugprone-parent-virtual-call",
@@ -94,41 +97,42 @@
"-performance-no-int-to-ptr",
]
+audioflinger_base_cflags = [
+ "-Wall",
+ "-Wdeprecated",
+ "-Werror",
+ "-Werror=implicit-fallthrough",
+ "-Werror=sometimes-uninitialized",
+ "-Werror=conditional-uninitialized",
+ "-Wextra",
+
+ // suppress some warning chatter.
+ "-Wno-deprecated-copy-with-dtor",
+ "-Wno-deprecated-copy-with-user-provided-dtor",
+
+ "-Wredundant-decls",
+ "-Wshadow",
+ "-Wstrict-aliasing",
+ "-fstrict-aliasing",
+ "-Wthread-safety",
+ //"-Wthread-safety-negative", // experimental - looks broken in R.
+ "-Wunreachable-code",
+ "-Wunreachable-code-break",
+ "-Wunreachable-code-return",
+ "-Wunused",
+ "-Wused-but-marked-unused",
+]
+
// Eventually use common tidy defaults
cc_defaults {
name: "audioflinger_flags_defaults",
// https://clang.llvm.org/docs/UsersManual.html#command-line-options
// https://clang.llvm.org/docs/DiagnosticsReference.html
- cflags: [
- "-Wall",
- "-Wdeprecated",
- "-Werror",
- "-Werror=implicit-fallthrough",
- "-Werror=sometimes-uninitialized",
- "-Werror=conditional-uninitialized",
- "-Wextra",
-
- // suppress some warning chatter.
- "-Wno-deprecated-copy-with-dtor",
- "-Wno-deprecated-copy-with-user-provided-dtor",
-
- "-Wredundant-decls",
- "-Wshadow",
- "-Wstrict-aliasing",
- "-fstrict-aliasing",
- "-Wthread-safety",
- //"-Wthread-safety-negative", // experimental - looks broken in R.
- "-Wunreachable-code",
- "-Wunreachable-code-break",
- "-Wunreachable-code-return",
- "-Wunused",
- "-Wused-but-marked-unused",
- "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
- ],
+ cflags: audioflinger_base_cflags,
// https://clang.llvm.org/extra/clang-tidy/
tidy: true,
- tidy_checks: tidy_errors,
- tidy_checks_as_errors: tidy_errors,
+ tidy_checks: audioflinger_tidy_errors,
+ tidy_checks_as_errors: audioflinger_tidy_errors,
tidy_flags: [
"-format-style=file",
],
@@ -145,31 +149,14 @@
srcs: [
"AudioFlinger.cpp",
- "AudioHwDevice.cpp",
- "AudioStreamOut.cpp",
- "AudioWatchdog.cpp",
- "BufLog.cpp",
"DeviceEffectManager.cpp",
"Effects.cpp",
- "FastCapture.cpp",
- "FastCaptureDumpState.cpp",
- "FastCaptureState.cpp",
- "FastMixer.cpp",
- "FastMixerDumpState.cpp",
- "FastMixerState.cpp",
- "FastThread.cpp",
- "FastThreadDumpState.cpp",
- "FastThreadState.cpp",
"MelReporter.cpp",
- "NBAIO_Tee.cpp",
"PatchCommandThread.cpp",
"PatchPanel.cpp",
"PropertyUtils.cpp",
- "SpdifStreamOut.cpp",
- "StateQueue.cpp",
"Threads.cpp",
"Tracks.cpp",
- "TypedLogger.cpp",
],
include_dirs: [
@@ -184,7 +171,10 @@
"effect-aidl-cpp",
"libaudioclient_aidl_conversion",
"libactivitymanager_aidl",
+ "libaudioflinger_datapath",
+ "libaudioflinger_fastpath",
"libaudioflinger_timing",
+ "libaudioflinger_utils",
"libaudiofoundation",
"libaudiohal",
"libaudioprocessing",
@@ -214,7 +204,6 @@
static_libs: [
"libcpustats",
- "libsndfile",
"libpermission",
],
@@ -232,7 +221,6 @@
],
cflags: [
- "-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
"-fvisibility=hidden",
"-Werror",
"-Wall",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 325adfa..6406c6f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -59,7 +59,6 @@
#include "AudioFlinger.h"
#include "EffectConfiguration.h"
-#include "NBAIO_Tee.h"
#include "PropertyUtils.h"
#include <media/AudioResamplerPublic.h>
@@ -87,9 +86,8 @@
#include <private/android_filesystem_config.h>
//#define BUFLOG_NDEBUG 0
-#include <BufLog.h>
-
-#include "TypedLogger.h"
+#include <afutils/BufLog.h>
+#include <afutils/TypedLogger.h>
// ----------------------------------------------------------------------------
@@ -731,24 +729,24 @@
}
}
-status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
+status_t AudioFlinger::addEffectToHal(
+ const struct audio_port_config *device, const sp<EffectHalInterface>& 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<EffectHalInterface>& effect) {
+status_t AudioFlinger::removeEffectFromHal(
+ const struct audio_port_config *device, const sp<EffectHalInterface>& 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[] = {
@@ -1262,18 +1260,19 @@
}
// Look for sync events awaiting for a session to be used.
- for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
- if (mPendingSyncEvents[i]->triggerSession() == sessionId) {
- if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
+ for (auto it = mPendingSyncEvents.begin(); it != mPendingSyncEvents.end();) {
+ if ((*it)->triggerSession() == sessionId) {
+ if (thread->isValidSyncEvent(*it)) {
if (lStatus == NO_ERROR) {
- (void) track->setSyncEvent(mPendingSyncEvents[i]);
+ (void) track->setSyncEvent(*it);
} else {
- mPendingSyncEvents[i]->cancel();
+ (*it)->cancel();
}
- mPendingSyncEvents.removeAt(i);
- i--;
+ it = mPendingSyncEvents.erase(it);
+ continue;
}
}
+ ++it;
}
if ((output.flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
setAudioHwSyncForSession_l(thread, sessionId);
@@ -3001,14 +3000,6 @@
return nullptr;
}
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
- ALOGE("openOutput_l() cannot create spatializer thread "
- "without #define MULTICHANNEL_EFFECT_CHAIN");
- return nullptr;
- }
-#endif
-
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
// FOR TESTING ONLY:
@@ -4003,15 +3994,16 @@
track->setTeePatchesToUpdate(std::move(teePatches));
}
-sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
+sp<audioflinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
- sync_event_callback_t callBack,
+ const audioflinger::SyncEventCallback& callBack,
const wp<RefBase>& cookie)
{
Mutex::Autolock _l(mLock);
- sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
+ auto event = sp<audioflinger::SyncEvent>::make(
+ type, triggerSession, listenerSession, callBack, cookie);
status_t playStatus = NAME_NOT_FOUND;
status_t recStatus = NAME_NOT_FOUND;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -4027,7 +4019,7 @@
}
}
if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
- mPendingSyncEvents.add(event);
+ mPendingSyncEvents.emplace_back(event);
} else {
ALOGV("createSyncEvent() invalid event %d", event->type());
event.clear();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 10bfdb9..320975e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -79,6 +79,9 @@
#include <mediautils/Synchronization.h>
#include <mediautils/ThreadSnapshot.h>
+#include <afutils/AudioWatchdog.h>
+#include <afutils/NBAIO_Tee.h>
+
#include <audio_utils/clock.h>
#include <audio_utils/FdToString.h>
#include <audio_utils/LinearMap.h>
@@ -89,17 +92,18 @@
#include <sounddose/SoundDoseManager.h>
#include <timing/MonotonicFrameCounter.h>
+#include <timing/SyncEvent.h>
+#include <timing/SynchronizedRecordState.h>
-#include "FastCapture.h"
-#include "FastMixer.h"
+#include <datapath/AudioHwDevice.h>
+#include <datapath/AudioStreamOut.h>
+#include <datapath/SpdifStreamOut.h>
+#include <datapath/ThreadMetrics.h>
+#include <datapath/TrackMetrics.h>
+#include <fastpath/FastCapture.h>
+#include <fastpath/FastMixer.h>
#include <media/nbaio/NBAIO.h>
-#include "AudioWatchdog.h"
-#include "AudioStreamOut.h"
-#include "SpdifStreamOut.h"
-#include "AudioHwDevice.h"
-#include "NBAIO_Tee.h"
-#include "ThreadMetrics.h"
-#include "TrackMetrics.h"
+
#include "AllocatorFactory.h"
#include <android/os/IPowerManager.h>
@@ -344,10 +348,10 @@
const sp<os::ExternalVibration>& externalVibration);
static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
- status_t addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
- status_t removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
+ status_t addEffectToHal(
+ const struct audio_port_config *device, const sp<EffectHalInterface>& effect);
+ status_t removeEffectFromHal(
+ const struct audio_port_config *device, const sp<EffectHalInterface>& effect);
void updateDownStreamPatches_l(const struct audio_patch *patch,
const std::set<audio_io_handle_t>& streams);
@@ -383,47 +387,10 @@
static inline std::atomic<AudioFlinger *> gAudioFlinger = nullptr;
- class SyncEvent;
-
- typedef void (*sync_event_callback_t)(const wp<SyncEvent>& event) ;
-
- class SyncEvent : public RefBase {
- public:
- SyncEvent(AudioSystem::sync_event_t type,
- audio_session_t triggerSession,
- audio_session_t listenerSession,
- sync_event_callback_t callBack,
- const wp<RefBase>& cookie)
- : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
- mCallback(callBack), mCookie(cookie)
- {}
-
- virtual ~SyncEvent() {}
-
- void trigger() {
- Mutex::Autolock _l(mLock);
- if (mCallback) mCallback(wp<SyncEvent>(this));
- }
- bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
- void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
- AudioSystem::sync_event_t type() const { return mType; }
- audio_session_t triggerSession() const { return mTriggerSession; }
- audio_session_t listenerSession() const { return mListenerSession; }
- wp<RefBase> cookie() const { return mCookie; }
-
- private:
- const AudioSystem::sync_event_t mType;
- const audio_session_t mTriggerSession;
- const audio_session_t mListenerSession;
- sync_event_callback_t mCallback;
- const wp<RefBase> mCookie;
- mutable Mutex mLock;
- };
-
- sp<SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+ sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
- sync_event_callback_t callBack,
+ const audioflinger::SyncEventCallback& callBack,
const wp<RefBase>& cookie);
bool btNrecIsOff() const { return mBtNrecIsOff.load(); }
@@ -643,13 +610,6 @@
};
// --- PlaybackThread ---
-#ifdef FLOAT_EFFECT_CHAIN
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
-using effect_buffer_t = float;
-#else
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_16_BIT
-using effect_buffer_t = int16_t;
-#endif
#include "Threads.h"
@@ -994,8 +954,8 @@
bool masterMute_l() const;
AudioHwDevice* loadHwModule_l(const char *name);
- Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session
- // to be created
+ // sync events awaiting for a session to be created.
+ std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
// Effect chains without a valid thread
DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
diff --git a/services/audioflinger/AudioWatchdog.h b/services/audioflinger/AudioWatchdog.h
deleted file mode 100644
index 7b69fc6..0000000
--- a/services/audioflinger/AudioWatchdog.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-// The watchdog thread runs periodically. It has two functions:
-// (a) verify that adequate CPU time is available, and log
-// as soon as possible when there appears to be a CPU shortage
-// (b) monitor the other threads [not yet implemented]
-
-#ifndef AUDIO_WATCHDOG_H
-#define AUDIO_WATCHDOG_H
-
-#include <time.h>
-#include <utils/Thread.h>
-
-namespace android {
-
-// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
-// The usual caveats about atomicity of information apply.
-struct AudioWatchdogDump {
- AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { }
- /*virtual*/ ~AudioWatchdogDump() { }
- uint32_t mUnderruns; // total number of underruns
- uint32_t mLogs; // total number of log messages
- time_t mMostRecent; // time of most recent log
- void dump(int fd); // should only be called on a stable copy, not the original
-};
-
-class AudioWatchdog : public Thread {
-
-public:
- explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
- mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
- // mOldTs
- // mLogTs initialized below
- mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
- {
-#define MIN_TIME_BETWEEN_LOGS_SEC 60
- // force an immediate log on first underrun
- mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
- mLogTs.tv_nsec = 0;
- }
- virtual ~AudioWatchdog() { }
-
- // Do not call Thread::requestExitAndWait() without first calling requestExit().
- // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
- virtual void requestExit();
-
- // FIXME merge API and implementation with AudioTrackThread
- void pause(); // suspend thread from execution at next loop boundary
- void resume(); // allow thread to execute, if not requested to exit
-
- // Where to store the dump, or NULL to not update
- void setDump(AudioWatchdogDump* dump);
-
-private:
- virtual bool threadLoop();
-
- Mutex mMyLock; // Thread::mLock is private
- Condition mMyCond; // Thread::mThreadExitedCondition is private
- bool mPaused; // whether thread is currently paused
-
- uint32_t mPeriodNs; // nominal period
- uint32_t mMaxCycleNs; // maximum allowed time of one cycle before declaring underrun
- struct timespec mOldTs; // monotonic time when threadLoop last ran
- struct timespec mLogTs; // time since last log
- bool mOldTsValid; // whether mOldTs is valid
- uint32_t mUnderruns; // total number of underruns
- uint32_t mLogs; // total number of logs
- AudioWatchdogDump* mDump; // where to store the dump, always non-NULL
- AudioWatchdogDump mDummyDump; // default area for dump in case setDump() is not called
-};
-
-} // namespace android
-
-#endif // AUDIO_WATCHDOG_H
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index ede8e3f..845697a 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -41,15 +41,4 @@
// uncomment to log CPU statistics every n wall clock seconds
//#define DEBUG_CPU_USAGE 10
-// define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable)
-#define FLOAT_EFFECT_CHAIN
-
-#ifdef FLOAT_EFFECT_CHAIN
-// define FLOAT_AUX to process aux effect buffers in float (FLOAT_EFFECT_CHAIN must be defined)
-#define FLOAT_AUX
-
-// define MULTICHANNEL_EFFECT_CHAIN to allow multichannel effects (FLOAT_EFFECT_CHAIN defined)
-#define MULTICHANNEL_EFFECT_CHAIN
-#endif
-
#endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index 395781d..b87f830 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -44,13 +44,13 @@
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *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<EffectHalInterface>& 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<EffectHalInterface>& effect) {
- return mAudioFlinger.removeEffectFromHal(deviceId, hwModuleId, effect);
+ return mAudioFlinger.removeEffectFromHal(device, effect);
};
AudioFlinger& audioFlinger() const { return mAudioFlinger; }
@@ -132,13 +132,13 @@
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<EffectHalInterface>& effect) {
- return mManager.addEffectToHal(deviceId, hwModuleId, effect);
+ status_t addEffectToHal(const struct audio_port_config *device,
+ const sp<EffectHalInterface>& effect) {
+ return mManager.addEffectToHal(device, effect);
}
- status_t removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
- return mManager.removeEffectFromHal(deviceId, hwModuleId, effect);
+ status_t removeEffectFromHal(const struct audio_port_config *device,
+ const sp<EffectHalInterface>& effect) {
+ return mManager.removeEffectFromHal(device, effect);
}
private:
DeviceEffectManager& mManager;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 77aa804..822ea93 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -573,9 +573,7 @@
mDisableWaitCnt(0), // set by process() and updateState()
mOffloaded(false),
mIsOutput(false)
-#ifdef FLOAT_EFFECT_CHAIN
, mSupportsFloat(false)
-#endif
{
ALOGV("Constructor %p pinned %d", this, pinned);
int lStatus;
@@ -694,31 +692,16 @@
mConfig.inputCfg.buffer.frameCount,
mConfig.outputCfg.buffer.frameCount);
const auto accumulateInputToOutput = [this, safeInputOutputSampleCount]() {
-#ifdef FLOAT_EFFECT_CHAIN
accumulate_float(
mConfig.outputCfg.buffer.f32,
mConfig.inputCfg.buffer.f32,
safeInputOutputSampleCount);
-#else
- accumulate_i16(
- mConfig.outputCfg.buffer.s16,
- mConfig.inputCfg.buffer.s16,
- safeInputOutputSampleCount);
-#endif
};
const auto copyInputToOutput = [this, safeInputOutputSampleCount]() {
-#ifdef FLOAT_EFFECT_CHAIN
memcpy(
mConfig.outputCfg.buffer.f32,
mConfig.inputCfg.buffer.f32,
safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.f32));
-
-#else
- memcpy(
- mConfig.outputCfg.buffer.s16,
- mConfig.inputCfg.buffer.s16,
- safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.s16));
-#endif
};
if (isProcessEnabled()) {
@@ -727,35 +710,14 @@
if (auxType) {
// We overwrite the aux input buffer here and clear after processing.
// aux input is always mono.
-#ifdef FLOAT_EFFECT_CHAIN
- if (mSupportsFloat) {
-#ifndef FLOAT_AUX
- // Do in-place float conversion for auxiliary effect input buffer.
- static_assert(sizeof(float) <= sizeof(int32_t),
- "in-place conversion requires sizeof(float) <= sizeof(int32_t)");
- memcpy_to_float_from_q4_27(
- mConfig.inputCfg.buffer.f32,
- mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount);
-#endif // !FLOAT_AUX
- } else
-#endif // FLOAT_EFFECT_CHAIN
- {
-#ifdef FLOAT_AUX
+ if (!mSupportsFloat) {
memcpy_to_i16_from_float(
mConfig.inputCfg.buffer.s16,
mConfig.inputCfg.buffer.f32,
mConfig.inputCfg.buffer.frameCount);
-#else
- memcpy_to_i16_from_q4_27(
- mConfig.inputCfg.buffer.s16,
- mConfig.inputCfg.buffer.s32,
- mConfig.inputCfg.buffer.frameCount);
-#endif
}
}
-#ifdef FLOAT_EFFECT_CHAIN
sp<EffectBufferHalInterface> inBuffer = mInBuffer;
sp<EffectBufferHalInterface> outBuffer = mOutBuffer;
@@ -802,9 +764,7 @@
outBuffer = mOutConversionBuffer;
}
}
-#endif
ret = mEffectInterface->process();
-#ifdef FLOAT_EFFECT_CHAIN
if (!mSupportsFloat) { // convert output int16_t back to float.
sp<EffectBufferHalInterface> target =
mOutChannelCountRequested != outChannelCount
@@ -821,11 +781,8 @@
sizeof(float),
sizeof(float) * outChannelCount * mConfig.outputCfg.buffer.frameCount);
}
-#endif
} else {
-#ifdef FLOAT_EFFECT_CHAIN
data_bypass:
-#endif
if (!auxType /* aux effects do not require data bypass */
&& mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
@@ -844,13 +801,8 @@
// clear auxiliary effect input buffer for next accumulation
if (auxType) {
-#ifdef FLOAT_AUX
const size_t size =
mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(float);
-#else
- const size_t size =
- mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t);
-#endif
memset(mConfig.inputCfg.buffer.raw, 0, size);
}
} else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
@@ -905,23 +857,6 @@
ALOGV("Overriding auxiliary effect input channels %#x as MONO",
mConfig.inputCfg.channels);
}
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
- mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- ALOGV("Overriding auxiliary effect output channels %#x as STEREO",
- mConfig.outputCfg.channels);
- }
-#endif
- } else {
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- // TODO: Update this logic when multichannel effects are implemented.
- // For offloaded tracks consider mono output as stereo for proper effect initialization
- if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
- mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
- ALOGV("Overriding effect input and output as STEREO");
- }
-#endif
}
if (isHapticGenerator()) {
audio_channel_mask_t hapticChannelMask = callback->hapticChannelMask();
@@ -933,8 +868,8 @@
mOutChannelCountRequested =
audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
- mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
- mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
+ mConfig.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+ mConfig.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
// Don't use sample rate for thread if effect isn't offloadable.
if (callback->isOffloadOrDirect() && !isOffloaded()) {
@@ -982,7 +917,6 @@
status = cmdStatus;
}
-#ifdef MULTICHANNEL_EFFECT_CHAIN
if (status != NO_ERROR &&
EffectConfiguration::isHidl() && // only HIDL effects support channel conversion
mIsOutput &&
@@ -1008,9 +942,7 @@
status = cmdStatus;
}
}
-#endif
-#ifdef FLOAT_EFFECT_CHAIN
if (status == NO_ERROR) {
mSupportsFloat = true;
}
@@ -1036,7 +968,6 @@
ALOGE("%s failed %d with int16_t (as well as float)", __func__, status);
}
}
-#endif
if (status == NO_ERROR) {
// Establish Buffer strategy
@@ -1349,7 +1280,6 @@
mInBuffer = buffer;
mEffectInterface->setInBuffer(buffer);
-#ifdef FLOAT_EFFECT_CHAIN
// aux effects do in place conversion to float - we don't allocate mInConversionBuffer.
// Theoretically insert effects can also do in-place conversions (destroying
// the original buffer) when the output buffer is identical to the input buffer,
@@ -1381,7 +1311,6 @@
ALOGE("%s cannot create mInConversionBuffer", __func__);
}
}
-#endif
}
void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
@@ -1397,7 +1326,6 @@
mOutBuffer = buffer;
mEffectInterface->setOutBuffer(buffer);
-#ifdef FLOAT_EFFECT_CHAIN
// Note: Any effect that does not accumulate does not need mOutConversionBuffer and
// can do in-place conversion from int16_t to float. We don't optimize here.
const uint32_t outChannelCount =
@@ -1425,7 +1353,6 @@
ALOGE("%s cannot create mOutConversionBuffer", __func__);
}
}
-#endif
}
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
@@ -1721,15 +1648,12 @@
mConfig.outputCfg.format,
formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
-#ifdef FLOAT_EFFECT_CHAIN
-
result.appendFormat("\t\t- HAL buffers:\n"
"\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
dumpInOutBuffer(true /* isInput */, mInBuffer).c_str(),
dumpInOutBuffer(true /* isInput */, mInConversionBuffer).c_str(),
dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
-#endif
write(fd, result.string(), result.length());
@@ -2262,7 +2186,7 @@
if (mInBuffer == NULL) {
return;
}
- const size_t frameSize = audio_bytes_per_sample(EFFECT_BUFFER_FORMAT)
+ const size_t frameSize = audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT)
* mEffectCallback->inChannelCount(mEffects[0]->id());
memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
@@ -2363,13 +2287,9 @@
// calling the process in effect engine
size_t numSamples = mEffectCallback->frameCount();
sp<EffectBufferHalInterface> halBuffer;
-#ifdef FLOAT_EFFECT_CHAIN
+
status_t result = mEffectCallback->allocateHalBuffer(
numSamples * sizeof(float), &halBuffer);
-#else
- status_t result = mEffectCallback->allocateHalBuffer(
- numSamples * sizeof(int32_t), &halBuffer);
-#endif
if (result != OK) return result;
effect->configure();
@@ -2536,7 +2456,8 @@
// make sure the input buffer configuration for the new first effect in the chain
// is updated if needed (can switch from HAL channel mask to mixer channel mask)
- if (i == 0 && size > 1) {
+ if (type != EFFECT_FLAG_TYPE_AUXILIARY // TODO(b/284522658) breaks for aux FX, why?
+ && i == 0 && size > 1) {
mEffects[0]->configure();
mEffects[0]->setInBuffer(mInBuffer);
mEffects[0]->updateAccessMode(); // reconfig if neeeded.
@@ -3486,8 +3407,7 @@
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 +3415,7 @@
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 {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 885d3e5..57acc67 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -323,13 +323,11 @@
audio_io_handle_t mCurrentHalStream = AUDIO_IO_HANDLE_NONE;
bool mIsOutput; // direction of the AF thread
-#ifdef FLOAT_EFFECT_CHAIN
bool mSupportsFloat; // effect supports float processing
sp<EffectBufferHalInterface> mInConversionBuffer; // Buffers for HAL conversion if needed.
sp<EffectBufferHalInterface> mOutConversionBuffer;
uint32_t mInChannelCountRequested;
uint32_t mOutChannelCountRequested;
-#endif
class AutoLockReentrant {
public:
@@ -494,14 +492,14 @@
void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
mInBuffer = buffer;
}
- effect_buffer_t *inBuffer() const {
- return mInBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mInBuffer->ptr()) : NULL;
+ float *inBuffer() const {
+ return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
}
void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
mOutBuffer = buffer;
}
- effect_buffer_t *outBuffer() const {
- return mOutBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mOutBuffer->ptr()) : NULL;
+ float *outBuffer() const {
+ return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
}
void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
diff --git a/services/audioflinger/FastCapture.h b/services/audioflinger/FastCapture.h
deleted file mode 100644
index c3817c0..0000000
--- a/services/audioflinger/FastCapture.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_AUDIO_FAST_CAPTURE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_H
-
-#include "FastThread.h"
-#include "StateQueue.h"
-#include "FastCaptureState.h"
-#include "FastCaptureDumpState.h"
-
-namespace android {
-
-typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
-
-class FastCapture : public FastThread {
-
-public:
- FastCapture();
- virtual ~FastCapture();
-
- FastCaptureStateQueue* sq();
-
-private:
- FastCaptureStateQueue mSQ;
-
- // callouts
- virtual const FastThreadState *poll();
- virtual void setNBLogWriter(NBLog::Writer *logWriter);
- virtual void onIdle();
- virtual void onExit();
- virtual bool isSubClassCommand(FastThreadState::Command command);
- virtual void onStateChange();
- virtual void onWork();
-
- static const FastCaptureState sInitial;
-
- FastCaptureState mPreIdle; // copy of state before we went into idle
- // FIXME by renaming, could pull up many of these to FastThread
- NBAIO_Source* mInputSource;
- int mInputSourceGen;
- NBAIO_Sink* mPipeSink;
- int mPipeSinkGen;
- void* mReadBuffer;
- ssize_t mReadBufferState; // number of initialized frames in readBuffer,
- // or -1 to clear
- NBAIO_Format mFormat;
- unsigned mSampleRate;
- FastCaptureDumpState mDummyFastCaptureDumpState;
- uint32_t mTotalNativeFramesRead; // copied to dumpState->mFramesRead
-
-}; // class FastCapture
-
-} // namespace android
-
-#endif // ANDROID_AUDIO_FAST_CAPTURE_H
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
deleted file mode 100644
index 2f0f73f..0000000
--- a/services/audioflinger/FastThread.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2014 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 ANDROID_AUDIO_FAST_THREAD_H
-#define ANDROID_AUDIO_FAST_THREAD_H
-
-#include "Configuration.h"
-#ifdef CPU_FREQUENCY_STATISTICS
-#include <cpustats/ThreadCpuUsage.h>
-#endif
-#include <utils/Thread.h>
-#include "FastThreadState.h"
-
-namespace android {
-
-// FastThread is the common abstract base class of FastMixer and FastCapture
-class FastThread : public Thread {
-
-public:
- FastThread(const char *cycleMs, const char *loadUs);
- virtual ~FastThread();
-
-private:
- // implement Thread::threadLoop()
- virtual bool threadLoop();
-
-protected:
- // callouts to subclass in same lexical order as they were in original FastMixer.cpp
- // FIXME need comments
- virtual const FastThreadState *poll() = 0;
- virtual void setNBLogWriter(NBLog::Writer *logWriter __unused) { }
- virtual void onIdle() = 0;
- virtual void onExit() = 0;
- virtual bool isSubClassCommand(FastThreadState::Command command) = 0;
- virtual void onStateChange() = 0;
- virtual void onWork() = 0;
-
- // FIXME these former local variables need comments
- const FastThreadState* mPrevious;
- const FastThreadState* mCurrent;
- struct timespec mOldTs;
- bool mOldTsValid;
- long mSleepNs; // -1: busy wait, 0: sched_yield, > 0: nanosleep
- long mPeriodNs; // expected period; the time required to render one mix buffer
- long mUnderrunNs; // underrun likely when write cycle is greater than this value
- long mOverrunNs; // overrun likely when write cycle is less than this value
- long mForceNs; // if overrun detected,
- // force the write cycle to take this much time
- long mWarmupNsMin; // warmup complete when write cycle is greater than or equal to
- // this value
- long mWarmupNsMax; // and less than or equal to this value
- FastThreadDumpState* mDummyDumpState;
- FastThreadDumpState* mDumpState;
- bool mIgnoreNextOverrun; // used to ignore initial overrun and first after an
- // underrun
-#ifdef FAST_THREAD_STATISTICS
- struct timespec mOldLoad; // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
- bool mOldLoadValid; // whether oldLoad is valid
- uint32_t mBounds;
- bool mFull; // whether we have collected at least mSamplingN samples
-#ifdef CPU_FREQUENCY_STATISTICS
- ThreadCpuUsage mTcu; // for reading the current CPU clock frequency in kHz
-#endif
-#endif
- unsigned mColdGen; // last observed mColdGen
- bool mIsWarm; // true means ready to mix,
- // false means wait for warmup before mixing
- struct timespec mMeasuredWarmupTs; // how long did it take for warmup to complete
- uint32_t mWarmupCycles; // counter of number of loop cycles during warmup phase
- uint32_t mWarmupConsecutiveInRangeCycles; // number of consecutive cycles in range
- const sp<NBLog::Writer> mDummyNBLogWriter{new NBLog::Writer()};
- status_t mTimestampStatus;
-
- FastThreadState::Command mCommand;
- bool mAttemptedWrite;
-
- char mCycleMs[16]; // cycle_ms + suffix
- char mLoadUs[16]; // load_us + suffix
-
-}; // class FastThread
-
-} // namespace android
-
-#endif // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 0e1a3c9..51bb93b 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -117,8 +117,8 @@
status_t attachAuxEffect(int EffectId);
void setAuxBuffer(int EffectId, int32_t *buffer);
int32_t *auxBuffer() const { return mAuxBuffer; }
- void setMainBuffer(effect_buffer_t *buffer) { mMainBuffer = buffer; }
- effect_buffer_t *mainBuffer() const { return mMainBuffer; }
+ void setMainBuffer(float *buffer) { mMainBuffer = buffer; }
+ float *mainBuffer() const { return mMainBuffer; }
int auxEffectId() const { return mAuxEffectId; }
virtual status_t getTimestamp(AudioTimestamp& timestamp);
void signal();
@@ -132,7 +132,7 @@
// implement FastMixerState::VolumeProvider interface
virtual gain_minifloat_packed_t getVolumeLR();
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
virtual bool isFastTrack() const { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
@@ -297,7 +297,7 @@
bool mResetDone;
const audio_stream_type_t mStreamType;
- effect_buffer_t *mMainBuffer;
+ float *mMainBuffer;
int32_t *mAuxBuffer;
int mAuxEffectId;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index f0a5f76..d91a210 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -58,7 +58,7 @@
void appendDumpHeader(String8& result);
void appendDump(String8& result, bool active);
- void handleSyncStartEvent(const sp<SyncEvent>& event);
+ void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event);
void clearSyncStartEvent();
void updateTrackFrameInfo(int64_t trackFramesReleased,
@@ -107,12 +107,10 @@
// sync event triggering actual audio capture. Frames read before this event will
// be dropped and therefore not read by the application.
- sp<SyncEvent> mSyncStartEvent;
+ sp<audioflinger::SyncEvent> mSyncStartEvent;
- // number of captured frames to drop after the start sync event has been received.
- // when < 0, maximum frames to drop before starting capture even if sync event is
- // not received
- ssize_t mFramesToDrop;
+ audioflinger::SynchronizedRecordState
+ mSynchronizedRecordState{mSampleRate}; // sampleRate defined in base
// used by resampler to find source frames
ResamplerBufferProvider *mResamplerBufferProvider;
diff --git a/services/audioflinger/StateQueueInstantiations.cpp b/services/audioflinger/StateQueueInstantiations.cpp
deleted file mode 100644
index 6f4505e..0000000
--- a/services/audioflinger/StateQueueInstantiations.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 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 "Configuration.h"
-#include "FastMixerState.h"
-#include "FastCaptureState.h"
-#include "StateQueue.h"
-
-// FIXME hack for gcc
-
-namespace android {
-
-template class StateQueue<FastMixerState>; // typedef FastMixerStateQueue
-template class StateQueue<FastCaptureState>; // typedef FastCaptureStateQueue
-
-}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 700bdd2..95883d9 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -76,8 +76,6 @@
#include <media/audiohal/StreamHalInterface.h>
#include "AudioFlinger.h"
-#include "FastMixer.h"
-#include "FastCapture.h"
#include <mediautils/SchedulingPolicyService.h>
#include <mediautils/ServiceUtilities.h>
@@ -91,10 +89,10 @@
#include <cpustats/ThreadCpuUsage.h>
#endif
-#include "AutoPark.h"
+#include <fastpath/AutoPark.h>
#include <pthread.h>
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
// ----------------------------------------------------------------------------
@@ -1410,15 +1408,6 @@
switch (mType) {
case MIXER: {
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- // Reject any effect on mixer multichannel sinks.
- // TODO: fix both format and multichannel issues with effects.
- if (mChannelCount != FCC_2) {
- ALOGW("%s: effect %s for multichannel(%d) on MIXER thread %s",
- __func__, desc->name, mChannelCount, mThreadName);
- return BAD_VALUE;
- }
-#endif
audio_output_flags_t flags = mOutput->flags;
if (hasFastMixer() || (flags & AUDIO_OUTPUT_FLAG_FAST)) {
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
@@ -1471,15 +1460,6 @@
__func__, desc->name, mThreadName);
return BAD_VALUE;
case DUPLICATING:
-#ifndef MULTICHANNEL_EFFECT_CHAIN
- // Reject any effect on mixer multichannel sinks.
- // TODO: fix both format and multichannel issues with effects.
- if (mChannelCount != FCC_2) {
- ALOGW("%s: effect %s for multichannel(%d) on DUPLICATING thread %s",
- __func__, desc->name, mChannelCount, mThreadName);
- return BAD_VALUE;
- }
-#endif
if (audio_is_global_session(sessionId)) {
ALOGW("%s: global effect %s on DUPLICATING thread %s",
__func__, desc->name, mThreadName);
@@ -3200,7 +3180,7 @@
free(mEffectBuffer);
mEffectBuffer = NULL;
if (mEffectBufferEnabled) {
- mEffectBufferFormat = EFFECT_BUFFER_FORMAT;
+ mEffectBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
mEffectBufferSize = mNormalFrameCount * mixerChannelCount
* audio_bytes_per_sample(mEffectBufferFormat);
(void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
@@ -3357,7 +3337,7 @@
return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
}
-status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<audioflinger::SyncEvent>& event)
{
if (!isValidSyncEvent(event)) {
return BAD_VALUE;
@@ -3376,7 +3356,8 @@
return NAME_NOT_FOUND;
}
-bool AudioFlinger::PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event) const
+bool AudioFlinger::PlaybackThread::isValidSyncEvent(
+ const sp<audioflinger::SyncEvent>& event) const
{
return event->type() == AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
}
@@ -3640,7 +3621,7 @@
{
audio_session_t session = chain->sessionId();
sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
- effect_buffer_t *buffer = nullptr; // only used for non global sessions
+ float *buffer = nullptr; // only used for non global sessions
if (mType == SPATIALIZER) {
if (!audio_is_global_session(session)) {
@@ -3658,7 +3639,7 @@
size_t numSamples = mNormalFrameCount
* (audio_channel_count_from_out_mask(channelMask) + mHapticChannelCount);
status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
- numSamples * sizeof(effect_buffer_t),
+ numSamples * sizeof(float),
&halInBuffer);
if (result != OK) return result;
@@ -3668,11 +3649,8 @@
&halOutBuffer);
if (result != OK) return result;
-#ifdef FLOAT_EFFECT_CHAIN
buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
-#else
- buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
-#endif
+
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
} else {
@@ -3700,7 +3678,7 @@
halOutBuffer = halInBuffer;
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
if (!audio_is_global_session(session)) {
- buffer = halInBuffer ? reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData())
+ buffer = halInBuffer ? reinterpret_cast<float*>(halInBuffer->externalData())
: buffer;
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
@@ -3709,14 +3687,11 @@
* (audio_channel_count_from_out_mask(mMixerChannelMask)
+ mHapticChannelCount);
const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
- numSamples * sizeof(effect_buffer_t),
+ numSamples * sizeof(float),
&halInBuffer);
if (allocateStatus != OK) return allocateStatus;
-#ifdef FLOAT_EFFECT_CHAIN
+
buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
-#else
- buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
-#endif
ALOGV("addEffectChain_l() creating new input buffer %p session %d",
buffer, session);
}
@@ -3800,7 +3775,7 @@
for (size_t j = 0; j < mTracks.size(); ++j) {
sp<Track> track = mTracks[j];
if (session == track->sessionId()) {
- track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
+ track->setMainBuffer(reinterpret_cast<float*>(mSinkBuffer));
chain->decTrackCnt();
}
}
@@ -3853,7 +3828,7 @@
bool AudioFlinger::PlaybackThread::threadLoop()
NO_THREAD_SAFETY_ANALYSIS // manual locking of AudioFlinger
{
- tlNBLogWriter = mNBLogWriter.get();
+ aflog::setThreadWriter(mNBLogWriter.get());
Vector< sp<Track> > tracksToRemove;
@@ -4220,12 +4195,12 @@
const size_t audioBufferSize = mNormalFrameCount
* audio_bytes_per_frame(hapticSessionChannelCount,
- EFFECT_BUFFER_FORMAT);
+ AUDIO_FORMAT_PCM_FLOAT);
memcpy_by_audio_format(
(uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
- EFFECT_BUFFER_FORMAT,
+ AUDIO_FORMAT_PCM_FLOAT,
(const uint8_t*)effectChains[i]->inBuffer() + audioBufferSize,
- EFFECT_BUFFER_FORMAT, mNormalFrameCount * mHapticChannelCount);
+ AUDIO_FORMAT_PCM_FLOAT, mNormalFrameCount * mHapticChannelCount);
}
}
}
@@ -4718,7 +4693,8 @@
if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
if (*volume != mLeftVolFloat) {
result = mOutput->stream->setVolume(*volume, *volume);
- ALOGE_IF(result != OK,
+ // HAL can return INVALID_OPERATION if operation is not supported.
+ ALOGE_IF(result != OK && result != INVALID_OPERATION,
"Error when setting output stream volume: %d", result);
if (result == NO_ERROR) {
mLeftVolFloat = *volume;
@@ -5916,7 +5892,7 @@
mAudioMixer->setParameter(
trackId,
AudioMixer::TRACK,
- AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
+ AudioMixer::MIXER_FORMAT, (void *)AUDIO_FORMAT_PCM_FLOAT);
mAudioMixer->setParameter(
trackId,
AudioMixer::TRACK,
@@ -8464,7 +8440,11 @@
overrun = OVERRUN_FALSE;
}
- if (activeTrack->mFramesToDrop == 0) {
+ // MediaSyncEvent handling: Synchronize AudioRecord to AudioTrack completion.
+ const ssize_t framesToDrop =
+ activeTrack->mSynchronizedRecordState.updateRecordFrames(framesOut);
+ if (framesToDrop == 0) {
+ // no sync event, process normally, otherwise ignore.
if (framesOut > 0) {
activeTrack->mSink.frameCount = framesOut;
// Sanitize before releasing if the track has no access to the source data
@@ -8474,28 +8454,7 @@
}
activeTrack->releaseBuffer(&activeTrack->mSink);
}
- } else {
- // FIXME could do a partial drop of framesOut
- if (activeTrack->mFramesToDrop > 0) {
- activeTrack->mFramesToDrop -= (ssize_t)framesOut;
- if (activeTrack->mFramesToDrop <= 0) {
- activeTrack->clearSyncStartEvent();
- }
- } else {
- activeTrack->mFramesToDrop += framesOut;
- if (activeTrack->mFramesToDrop >= 0 || activeTrack->mSyncStartEvent == 0 ||
- activeTrack->mSyncStartEvent->isCancelled()) {
- ALOGW("Synced record %s, session %d, trigger session %d",
- (activeTrack->mFramesToDrop >= 0) ? "timed out" : "cancelled",
- activeTrack->sessionId(),
- (activeTrack->mSyncStartEvent != 0) ?
- activeTrack->mSyncStartEvent->triggerSession() :
- AUDIO_SESSION_NONE);
- activeTrack->clearSyncStartEvent();
- }
- }
}
-
if (framesOut == 0) {
break;
}
@@ -8828,20 +8787,10 @@
if (event == AudioSystem::SYNC_EVENT_NONE) {
recordTrack->clearSyncStartEvent();
} else if (event != AudioSystem::SYNC_EVENT_SAME) {
- recordTrack->mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
- triggerSession,
- recordTrack->sessionId(),
- syncStartEventCallback,
- recordTrack);
- // Sync event can be cancelled by the trigger session if the track is not in a
- // compatible state in which case we start record immediately
- if (recordTrack->mSyncStartEvent->isCancelled()) {
- recordTrack->clearSyncStartEvent();
- } else {
- // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs
- recordTrack->mFramesToDrop = -(ssize_t)
- ((AudioSystem::kSyncRecordStartTimeOutMs * recordTrack->mSampleRate) / 1000);
- }
+ recordTrack->mSynchronizedRecordState.startRecording(
+ mAudioFlinger->createSyncEvent(
+ event, triggerSession,
+ recordTrack->sessionId(), syncStartEventCallback, recordTrack));
}
{
@@ -8923,9 +8872,9 @@
}
}
-void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
+void AudioFlinger::RecordThread::syncStartEventCallback(const wp<audioflinger::SyncEvent>& event)
{
- sp<SyncEvent> strongEvent = event.promote();
+ sp<audioflinger::SyncEvent> strongEvent = event.promote();
if (strongEvent != 0) {
sp<RefBase> ptr = strongEvent->cookie().promote();
@@ -8964,12 +8913,14 @@
return false;
}
-bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event __unused) const
+bool AudioFlinger::RecordThread::isValidSyncEvent(
+ const sp<audioflinger::SyncEvent>& /* event */) const
{
return false;
}
-status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event __unused)
+status_t AudioFlinger::RecordThread::setSyncEvent(
+ const sp<audioflinger::SyncEvent>& event __unused)
{
#if 0 // This branch is currently dead code, but is preserved in case it will be needed in future
if (!isValidSyncEvent(event)) {
@@ -10536,12 +10487,13 @@
// and because it can cause a recursive mutex lock on stop().
}
-status_t AudioFlinger::MmapThread::setSyncEvent(const sp<SyncEvent>& event __unused)
+status_t AudioFlinger::MmapThread::setSyncEvent(const sp<audioflinger::SyncEvent>& /* event */)
{
return BAD_VALUE;
}
-bool AudioFlinger::MmapThread::isValidSyncEvent(const sp<SyncEvent>& event __unused) const
+bool AudioFlinger::MmapThread::isValidSyncEvent(
+ const sp<audioflinger::SyncEvent>& /* event */) const
{
return false;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index e88134b..b2700db 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -520,8 +520,8 @@
audio_session_t sessionId,
bool threadLocked);
- virtual status_t setSyncEvent(const sp<SyncEvent>& event) = 0;
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+ virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
// Return a reference to a per-thread heap which can be used to allocate IMemory
// objects that will be read-only to client processes, read/write to mediaserver,
@@ -1021,8 +1021,8 @@
status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
// Consider also removing and passing an explicit mMainBuffer initialization
// parameter to AF::PlaybackThread::Track::Track().
- effect_buffer_t *sinkBuffer() const {
- return reinterpret_cast<effect_buffer_t *>(mSinkBuffer); };
+ float *sinkBuffer() const {
+ return reinterpret_cast<float *>(mSinkBuffer); };
virtual void detachAuxEffect_l(int effectId);
status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
@@ -1038,8 +1038,8 @@
virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId);
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
// called with AudioFlinger lock held
bool invalidateTracks_l(audio_stream_type_t streamType);
@@ -1995,10 +1995,10 @@
// FIXME replace by Set [and implement Bag/Multiset for other uses].
KeyedVector<audio_session_t, bool> sessionIds() const;
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
+ status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+ bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
- static void syncStartEventCallback(const wp<SyncEvent>& event);
+ static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
virtual size_t frameCount() const { return mFrameCount; }
bool hasFastCapture() const { return mFastCapture != 0; }
@@ -2202,8 +2202,8 @@
// Note: using mActiveTracks as no mTracks here.
return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
}
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
- virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event);
+ virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const;
virtual void checkSilentMode_l() {}
virtual void processVolume_l() {}
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 254fb91..d5b6a98 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -67,7 +67,7 @@
pid_t creatorPid,
uid_t uid,
bool isOut,
- alloc_type alloc = ALLOC_CBLK,
+ const alloc_type alloc = ALLOC_CBLK,
track_type type = TYPE_DEFAULT,
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
std::string metricsId = {});
@@ -84,7 +84,7 @@
pid_t creatorPid() const { return mCreatorPid; }
audio_port_handle_t portId() const { return mPortId; }
- virtual status_t setSyncEvent(const sp<SyncEvent>& event);
+ virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event);
sp<IMemory> getBuffers() const { return mBufferMemory; }
void* buffer() const { return mBuffer; }
@@ -352,6 +352,7 @@
// this could be a track type if needed later
const wp<ThreadBase> mThread;
+ const alloc_type mAllocType;
/*const*/ sp<Client> mClient; // see explanation at ~TrackBase() why not const
sp<IMemory> mCblkMemory;
audio_track_cblk_t* mCblk;
@@ -375,7 +376,7 @@
const audio_session_t mSessionId;
uid_t mUid;
- Vector < sp<SyncEvent> >mSyncEvents;
+ std::list<sp<audioflinger::SyncEvent>> mSyncEvents;
const bool mIsOut;
sp<ServerProxy> mServerProxy;
const int mId;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 7d2c4db..00c88bc 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -90,12 +90,13 @@
pid_t creatorPid,
uid_t clientUid,
bool isOut,
- alloc_type alloc,
+ const alloc_type alloc,
track_type type,
audio_port_handle_t portId,
std::string metricsId)
: RefBase(),
mThread(thread),
+ mAllocType(alloc),
mClient(client),
mCblk(NULL),
// mBuffer, mBufferSize
@@ -277,6 +278,10 @@
// relying on the automatic clear() at end of scope.
mClient.clear();
}
+ if (mAllocType == ALLOC_LOCAL) {
+ free(mBuffer);
+ mBuffer = nullptr;
+ }
// flush the binder command buffer
IPCThreadState::self()->flushCommands();
}
@@ -298,9 +303,10 @@
mServerProxy->releaseBuffer(&buf);
}
-status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(
+ const sp<audioflinger::SyncEvent>& event)
{
- mSyncEvents.add(event);
+ mSyncEvents.emplace_back(event);
return NO_ERROR;
}
@@ -1673,12 +1679,13 @@
void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
{
- for (size_t i = 0; i < mSyncEvents.size();) {
- if (mSyncEvents[i]->type() == type) {
- mSyncEvents[i]->trigger();
- mSyncEvents.removeAt(i);
+ for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
+ if ((*it)->type() == type) {
+ ALOGV("%s: triggering SyncEvent type %d", __func__, type);
+ (*it)->trigger();
+ it = mSyncEvents.erase(it);
} else {
- ++i;
+ ++it;
}
}
}
@@ -1710,7 +1717,8 @@
return vlr;
}
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+ const sp<audioflinger::SyncEvent>& event)
{
if (isTerminated() || mState == PAUSED ||
((framesReady() == 0) && ((mSharedBuffer != 0) ||
@@ -1924,6 +1932,8 @@
}
}
+ ALOGV("%s: trackFramesReleased:%lld sinkFramesWritten:%lld setDrained: %d",
+ __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
mAudioTrackServerProxy->setDrained(drained);
// Set correction for flushed frames that are not accounted for in released.
local.mFlushed = mAudioTrackServerProxy->framesFlushed();
@@ -2498,7 +2508,6 @@
type, portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
mOverflow(false),
- mFramesToDrop(0),
mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
mRecordBufferConverter(NULL),
mFlags(flags),
@@ -2700,27 +2709,24 @@
result.append("\n");
}
-void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event)
+// This is invoked by SyncEvent callback.
+void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(
+ const sp<audioflinger::SyncEvent>& event)
{
- if (event == mSyncStartEvent) {
- ssize_t framesToDrop = 0;
- sp<ThreadBase> threadBase = mThread.promote();
- if (threadBase != 0) {
- // TODO: use actual buffer filling status instead of 2 buffers when info is available
- // from audio HAL
- framesToDrop = threadBase->mFrameCount * 2;
- }
- mFramesToDrop = framesToDrop;
+ size_t framesToDrop = 0;
+ sp<ThreadBase> threadBase = mThread.promote();
+ if (threadBase != 0) {
+ // TODO: use actual buffer filling status instead of 2 buffers when info is available
+ // from audio HAL
+ framesToDrop = threadBase->mFrameCount * 2;
}
+
+ mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
}
void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
{
- if (mSyncStartEvent != 0) {
- mSyncStartEvent->cancel();
- mSyncStartEvent.clear();
- }
- mFramesToDrop = 0;
+ mSynchronizedRecordState.clear();
}
void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
diff --git a/services/audioflinger/TypedLogger.cpp b/services/audioflinger/TypedLogger.cpp
deleted file mode 100644
index 57c206b..0000000
--- a/services/audioflinger/TypedLogger.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *
- * Copyright 2017, 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 "AudioFlinger"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <pthread.h>
-#include "TypedLogger.h"
-
-namespace android {
-thread_local NBLog::Writer *tlNBLogWriter;
-}
diff --git a/services/audioflinger/afutils/Android.bp b/services/audioflinger/afutils/Android.bp
new file mode 100644
index 0000000..4c03e07
--- /dev/null
+++ b/services/audioflinger/afutils/Android.bp
@@ -0,0 +1,60 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+// TODO(b/275642749) Reenable these warnings
+audioflinger_utils_tidy_errors = audioflinger_base_tidy_errors + [
+ "-misc-non-private-member-variables-in-classes",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_utils_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: audioflinger_base_cflags,
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: audioflinger_utils_tidy_errors,
+ tidy_checks_as_errors: audioflinger_utils_tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
+cc_library {
+ name: "libaudioflinger_utils",
+
+ defaults: [
+ "audioflinger_utils_flags_defaults",
+ ],
+
+ srcs: [
+ "AudioWatchdog.cpp",
+ "BufLog.cpp",
+ "NBAIO_Tee.cpp",
+ "TypedLogger.cpp",
+ ],
+
+ shared_libs: [
+ "libaudioutils",
+ "libbase",
+ "liblog",
+ "libnbaio",
+ "libnblog",
+ "libutils",
+ ],
+
+ static_libs: [
+ "libsndfile",
+ ],
+
+ include_dirs: [
+ "frameworks/av/services/audioflinger", // for configuration
+ ],
+}
diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/afutils/AudioWatchdog.cpp
similarity index 85%
rename from services/audioflinger/AudioWatchdog.cpp
rename to services/audioflinger/afutils/AudioWatchdog.cpp
index 877e776..48a07a5 100644
--- a/services/audioflinger/AudioWatchdog.cpp
+++ b/services/audioflinger/afutils/AudioWatchdog.cpp
@@ -38,12 +38,12 @@
mUnderruns, mLogs, buf);
}
-bool AudioWatchdog::threadLoop()
+bool AudioWatchdog::threadLoop() NO_THREAD_SAFETY_ANALYSIS // unique_lock
{
{
- AutoMutex _l(mMyLock);
+ std::unique_lock _l(mLock);
if (mPaused) {
- mMyCond.wait(mMyLock);
+ mCond.wait(_l);
// ignore previous timestamp after resume()
mOldTsValid = false;
// force an immediate log on first underrun after resume()
@@ -65,7 +65,7 @@
return true;
}
time_t sec = newTs.tv_sec - mOldTs.tv_sec;
- long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
+ auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
if (nsec < 0) {
--sec;
nsec += 1000000000;
@@ -81,7 +81,8 @@
}
}
mLogTs.tv_sec += sec;
- if ((mLogTs.tv_nsec += nsec) >= 1000000000) {
+ mLogTs.tv_nsec += nsec;
+ if (mLogTs.tv_nsec >= 1000000000) {
mLogTs.tv_sec++;
mLogTs.tv_nsec -= 1000000000;
}
@@ -89,7 +90,7 @@
mDump->mUnderruns = ++mUnderruns;
if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) {
mDump->mLogs = ++mLogs;
- mDump->mMostRecent = time(NULL);
+ mDump->mMostRecent = time(nullptr /* tloc */);
ALOGW("Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u",
mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs);
mLogTs.tv_sec = 0;
@@ -99,7 +100,7 @@
struct timespec req;
req.tv_sec = 0;
req.tv_nsec = mPeriodNs;
- rc = nanosleep(&req, NULL);
+ rc = nanosleep(&req, nullptr /* remaining */);
if (!((rc == 0) || (rc == -1 && errno == EINTR))) {
pause();
return false;
@@ -116,22 +117,23 @@
void AudioWatchdog::pause()
{
- AutoMutex _l(mMyLock);
+ const std::lock_guard _l(mLock);
mPaused = true;
}
void AudioWatchdog::resume()
{
- AutoMutex _l(mMyLock);
+ const std::lock_guard _l(mLock);
if (mPaused) {
mPaused = false;
- mMyCond.signal();
+ mCond.notify_one();
}
}
void AudioWatchdog::setDump(AudioWatchdogDump *dump)
{
- mDump = dump != NULL ? dump : &mDummyDump;
+ const std::lock_guard _l(mLock);
+ mDump = dump != nullptr ? dump : &mDummyDump;
}
} // namespace android
diff --git a/services/audioflinger/afutils/AudioWatchdog.h b/services/audioflinger/afutils/AudioWatchdog.h
new file mode 100644
index 0000000..1f5dad4
--- /dev/null
+++ b/services/audioflinger/afutils/AudioWatchdog.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+// The watchdog thread runs periodically. It has two functions:
+// (a) verify that adequate CPU time is available, and log
+// as soon as possible when there appears to be a CPU shortage
+// (b) monitor the other threads [not yet implemented]
+
+#pragma once
+
+#include <mutex>
+#include <time.h>
+#include <utils/Thread.h>
+
+namespace android {
+
+// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
+// The usual caveats about atomicity of information apply.
+struct AudioWatchdogDump {
+ uint32_t mUnderruns = 0; // total number of underruns
+ uint32_t mLogs = 0; // total number of log messages
+ time_t mMostRecent = 0; // time of most recent log
+ void dump(int fd); // should only be called on a stable copy, not the original
+};
+
+class AudioWatchdog : public Thread {
+
+public:
+ explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/),
+ mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2)
+ {
+ // force an immediate log on first underrun
+ mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
+ mLogTs.tv_nsec = 0;
+ }
+
+ // Do not call Thread::requestExitAndWait() without first calling requestExit().
+ // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
+ void requestExit() override;
+
+ // FIXME merge API and implementation with AudioTrackThread
+ void pause(); // suspend thread from execution at next loop boundary
+ void resume(); // allow thread to execute, if not requested to exit
+
+ // Where to store the dump, or NULL to not update
+ void setDump(AudioWatchdogDump* dump);
+
+private:
+ bool threadLoop() override;
+
+ static constexpr int32_t MIN_TIME_BETWEEN_LOGS_SEC = 60;
+ const uint32_t mPeriodNs; // nominal period
+ const uint32_t mMaxCycleNs; // maximum allowed time of one cycle before declaring underrun
+
+ mutable std::mutex mLock; // Thread::mLock is private
+ std::condition_variable mCond; // Thread::mThreadExitedCondition is private
+ bool mPaused GUARDED_BY(mLock) = false; // whether thread is currently paused
+ bool mOldTsValid GUARDED_BY(mLock) = false; // whether mOldTs is valid
+ struct timespec mOldTs GUARDED_BY(mLock); // monotonic time when threadLoop last ran
+ struct timespec mLogTs GUARDED_BY(mLock); // time since last log (ctor init).
+ uint32_t mUnderruns GUARDED_BY(mLock) = 0; // total number of underruns
+ uint32_t mLogs GUARDED_BY(mLock) = 0; // total number of logs
+
+ // where to store the dump, always non-NULL
+ AudioWatchdogDump* mDump GUARDED_BY(mLock) = &mDummyDump;
+ AudioWatchdogDump mDummyDump; // default area for dump in case setDump() is not called
+};
+
+} // namespace android
+
diff --git a/services/audioflinger/BufLog.cpp b/services/audioflinger/afutils/BufLog.cpp
similarity index 77%
rename from services/audioflinger/BufLog.cpp
rename to services/audioflinger/afutils/BufLog.cpp
index 5f6aca0..508022f 100644
--- a/services/audioflinger/BufLog.cpp
+++ b/services/audioflinger/afutils/BufLog.cpp
@@ -28,12 +28,14 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
+namespace android {
+
// ------------------------------
// BufLogSingleton
// ------------------------------
pthread_once_t onceControl = PTHREAD_ONCE_INIT;
-BufLog *BufLogSingleton::mInstance = NULL;
+BufLog *BufLogSingleton::mInstance = nullptr;
void BufLogSingleton::initOnce() {
mInstance = new BufLog();
@@ -49,55 +51,39 @@
}
bool BufLogSingleton::instanceExists() {
- return mInstance != NULL;
+ return mInstance != nullptr;
}
// ------------------------------
// BufLog
// ------------------------------
-BufLog::BufLog() {
- memset(mStreams, 0, sizeof(mStreams));
-}
-
BufLog::~BufLog() {
- android::Mutex::Autolock autoLock(mLock);
-
- for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
- BufLogStream *pBLStream = mStreams[id];
- if (pBLStream != NULL) {
- delete pBLStream ;
- mStreams[id] = NULL;
- }
- }
+ reset();
}
size_t BufLog::write(int streamid, const char *tag, int format, int channels,
int samplingRate, size_t maxBytes, const void *buf, size_t size) {
- unsigned int id = streamid % BUFLOG_MAXSTREAMS;
- android::Mutex::Autolock autoLock(mLock);
+ const unsigned int id = streamid % BUFLOG_MAXSTREAMS;
+ const std::lock_guard autoLock(mLock);
BufLogStream *pBLStream = mStreams[id];
- if (pBLStream == NULL) {
+ if (pBLStream == nullptr) {
pBLStream = mStreams[id] = new BufLogStream(id, tag, format, channels,
samplingRate, maxBytes);
- ALOG_ASSERT(pBLStream != NULL, "BufLogStream Failed to be created");
}
return pBLStream->write(buf, size);
}
void BufLog::reset() {
- android::Mutex::Autolock autoLock(mLock);
- ALOGV("Resetting all BufLogs");
+ const std::lock_guard autoLock(mLock);
int count = 0;
-
- for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
- BufLogStream *pBLStream = mStreams[id];
- if (pBLStream != NULL) {
+ for (auto &pBLStream : mStreams) {
+ if (pBLStream != nullptr) {
delete pBLStream;
- mStreams[id] = NULL;
+ pBLStream = nullptr;
count++;
}
}
@@ -115,9 +101,7 @@
unsigned int samplingRate,
size_t maxBytes = 0) : mId(id), mFormat(format), mChannels(channels),
mSamplingRate(samplingRate), mMaxBytes(maxBytes) {
- mByteCount = 0;
- mPaused = false;
- if (tag != NULL) {
+ if (tag != nullptr) {
(void)audio_utils_strlcpy(mTag, tag);
} else {
mTag[0] = 0;
@@ -129,7 +113,7 @@
//timestamp
char timeStr[16]; //size 16: format %Y%m%d%H%M%S 14 chars + string null terminator
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, nullptr);
struct tm tm;
localtime_r(&tv.tv_sec, &tm);
strftime(timeStr, sizeof(timeStr), "%Y%m%d%H%M%S", &tm);
@@ -139,7 +123,7 @@
ALOGV("data output: %s", logPath);
mFile = fopen(logPath, "wb");
- if (mFile != NULL) {
+ if (mFile != nullptr) {
ALOGV("Success creating file at: %p", mFile);
} else {
ALOGE("Error: could not create file BufLogStream %s", strerror(errno));
@@ -148,24 +132,24 @@
void BufLogStream::closeStream_l() {
ALOGV("Closing BufLogStream id:%d tag:%s", mId, mTag);
- if (mFile != NULL) {
+ if (mFile != nullptr) {
fclose(mFile);
- mFile = NULL;
+ mFile = nullptr;
}
}
BufLogStream::~BufLogStream() {
ALOGV("Destroying BufLogStream id:%d tag:%s", mId, mTag);
- android::Mutex::Autolock autoLock(mLock);
+ const std::lock_guard autoLock(mLock);
closeStream_l();
}
size_t BufLogStream::write(const void *buf, size_t size) {
size_t bytes = 0;
- if (!mPaused && mFile != NULL) {
- if (size > 0 && buf != NULL) {
- android::Mutex::Autolock autoLock(mLock);
+ if (!mPaused && mFile != nullptr) {
+ if (size > 0 && buf != nullptr) {
+ const std::lock_guard autoLock(mLock);
if (mMaxBytes > 0) {
size = MIN(size, mMaxBytes - mByteCount);
}
@@ -185,12 +169,14 @@
}
bool BufLogStream::setPause(bool pause) {
- bool old = mPaused;
+ const bool old = mPaused;
mPaused = pause;
return old;
}
void BufLogStream::finalize() {
- android::Mutex::Autolock autoLock(mLock);
+ const std::lock_guard autoLock(mLock);
closeStream_l();
}
+
+} // namespace android
diff --git a/services/audioflinger/BufLog.h b/services/audioflinger/afutils/BufLog.h
similarity index 92%
rename from services/audioflinger/BufLog.h
rename to services/audioflinger/afutils/BufLog.h
index 1b402f4..a58d073 100644
--- a/services/audioflinger/BufLog.h
+++ b/services/audioflinger/afutils/BufLog.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_BUFLOG_H
-#define ANDROID_AUDIO_BUFLOG_H
+#pragma once
/*
* BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
@@ -99,17 +98,18 @@
BufLogSingleton::instance()->reset(); } } while (0)
#endif
-
+#include <mutex>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
-#include <utils/Mutex.h>
//BufLog configuration
#define BUFLOGSTREAM_MAX_TAGSIZE 32
#define BUFLOG_BASE_PATH "/data/misc/audioserver"
#define BUFLOG_MAX_PATH_SIZE 300
+namespace android {
+
class BufLogStream {
public:
BufLogStream(unsigned int id,
@@ -135,26 +135,24 @@
void finalize();
private:
- bool mPaused;
const unsigned int mId;
- char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1];
const unsigned int mFormat;
const unsigned int mChannels;
const unsigned int mSamplingRate;
const size_t mMaxBytes;
- size_t mByteCount;
- FILE *mFile;
- mutable android::Mutex mLock;
+ char mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor.
+
+ mutable std::mutex mLock;
+ bool mPaused = false;
+ size_t mByteCount = 0;
+ FILE *mFile; // set in ctor
void closeStream_l();
};
-
class BufLog {
public:
- BufLog();
~BufLog();
- BufLog(BufLog const&) {};
// streamid: int [0:BUFLOG_MAXSTREAMS-1] buffer id.
// If a buffer doesn't exist, it is created the first time is referenced
@@ -181,9 +179,9 @@
void reset();
protected:
- static const unsigned int BUFLOG_MAXSTREAMS = 16;
- BufLogStream *mStreams[BUFLOG_MAXSTREAMS];
- mutable android::Mutex mLock;
+ static constexpr size_t BUFLOG_MAXSTREAMS = 16;
+ mutable std::mutex mLock;
+ BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{};
};
class BufLogSingleton {
@@ -196,4 +194,4 @@
static BufLog *mInstance;
};
-#endif //ANDROID_AUDIO_BUFLOG_H
+} // namespace android
diff --git a/services/audioflinger/NBAIO_Tee.cpp b/services/audioflinger/afutils/NBAIO_Tee.cpp
similarity index 90%
rename from services/audioflinger/NBAIO_Tee.cpp
rename to services/audioflinger/afutils/NBAIO_Tee.cpp
index 53083d5..49057ce 100644
--- a/services/audioflinger/NBAIO_Tee.cpp
+++ b/services/audioflinger/afutils/NBAIO_Tee.cpp
@@ -91,8 +91,8 @@
/** returns filename of created audio file, else empty string on failure. */
std::string create(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
@@ -109,8 +109,8 @@
/** creates an audio file from a reader functor passed in. */
status_t createInternal(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
@@ -123,7 +123,7 @@
std::string generateFilename(const std::string &suffix) const {
char fileTime[sizeof("YYYYmmdd_HHMMSS_\0")];
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, nullptr /* struct timezone */);
struct tm tm;
localtime_r(&tv.tv_sec, &tm);
LOG_ALWAYS_FATAL_IF(strftime(fileTime, sizeof(fileTime), "%Y%m%d_%H%M%S_", &tm) == 0,
@@ -159,30 +159,29 @@
// yet another ThreadPool implementation.
class ThreadPool {
public:
- ThreadPool(size_t size)
+ explicit ThreadPool(size_t size)
: mThreadPoolSize(size)
{ }
/** launches task "name" with associated function "func".
if the threadpool is exhausted, it will launch on calling function */
- status_t launch(const std::string &name, std::function<status_t()> func);
+ status_t launch(const std::string &name, const std::function<status_t()>& func);
private:
+ const size_t mThreadPoolSize;
std::mutex mLock;
std::list<std::pair<
- std::string, std::future<status_t>>> mFutures; // GUARDED_BY(mLock)
-
- const size_t mThreadPoolSize;
+ std::string, std::future<status_t>>> mFutures; // GUARDED_BY(mLock);
} mThreadPool;
- const std::string mPrefix;
- std::mutex mLock;
- std::string mDirectory; // GUARDED_BY(mLock)
- std::deque<std::string> mFiles; // GUARDED_BY(mLock) sorted list of files by creation time
-
static constexpr size_t FRAMES_PER_READ = 1024;
static constexpr size_t MAX_FILES_READ = 1024;
static constexpr size_t MAX_FILES_KEEP = 32;
+
+ const std::string mPrefix;
+ std::mutex mLock;
+ std::string mDirectory; // GUARDED_BY(mLock);
+ std::deque<std::string> mFiles; // GUARDED_BY(mLock); // sorted list of files by creation time
};
/* static */
@@ -200,7 +199,7 @@
const NBAIO_Format format = source->format();
bool firstRead = true;
- std::string filename = audioFileHandler.create(
+ const std::string filename = audioFileHandler.create(
// this functor must not hold references to stack
[firstRead, sinkSource] (void *buffer, size_t frames) mutable {
auto &source = sinkSource.second;
@@ -230,14 +229,16 @@
Pipe *pipe = new Pipe(frames, format);
size_t numCounterOffers = 0;
const NBAIO_Format offers[1] = {format};
- ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+ ssize_t index = pipe->negotiate(
+ offers, 1 /* numOffers */, nullptr /* counterOffers */, numCounterOffers);
if (index != 0) {
ALOGW("pipe failure to negotiate: %zd", index);
goto exit;
}
PipeReader *pipeReader = new PipeReader(*pipe);
numCounterOffers = 0;
- index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
+ index = pipeReader->negotiate(
+ offers, 1 /* numOffers */, nullptr /* counterOffers */, numCounterOffers);
if (index != 0) {
ALOGW("pipeReader failure to negotiate: %zd", index);
goto exit;
@@ -251,14 +252,14 @@
}
std::string AudioFileHandler::create(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
const std::string &suffix)
{
- const std::string filename = generateFilename(suffix);
+ std::string filename = generateFilename(suffix);
if (mThreadPool.launch(std::string("create ") + filename,
[=]() { return createInternal(reader, sampleRate, channelCount, format, filename); })
@@ -312,7 +313,7 @@
std::sort(files.begin() + toRemove, files.end());
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
mDirectory = directory;
mFiles = std::move(files);
@@ -330,13 +331,13 @@
std::vector<std::string> filesToRemove;
std::string dir;
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
if (!isDirectoryValid(mDirectory)) return NO_INIT;
dir = mDirectory;
if (mFiles.size() > MAX_FILES_KEEP) {
- size_t toRemove = mFiles.size() - MAX_FILES_KEEP;
+ const size_t toRemove = mFiles.size() - MAX_FILES_KEEP;
// use move and erase to efficiently transfer std::string
std::move(mFiles.begin(),
@@ -346,7 +347,7 @@
}
}
- std::string dirp = dir + "/";
+ const std::string dirp = dir + "/";
// remove files outside of lock for better concurrency.
for (const auto &file : filesToRemove) {
(void)unlink((dirp + file).c_str());
@@ -360,14 +361,14 @@
}
status_t AudioFileHandler::ThreadPool::launch(
- const std::string &name, std::function<status_t()> func)
+ const std::string &name, const std::function<status_t()>& func)
{
if (mThreadPoolSize > 1) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
if (mFutures.size() >= mThreadPoolSize) {
for (auto it = mFutures.begin(); it != mFutures.end();) {
const std::string &filename = it->first;
- std::future<status_t> &future = it->second;
+ const std::future<status_t> &future = it->second;
if (!future.valid() ||
future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
ALOGV("%s: future %s ready", __func__, filename.c_str());
@@ -389,8 +390,8 @@
}
status_t AudioFileHandler::createInternal(
- std::function<ssize_t /* frames_read */
- (void * /* buffer */, size_t /* size_in_frames */)> reader,
+ const std::function<ssize_t /* frames_read */
+ (void * /* buffer */, size_t /* size_in_frames */)>& reader,
uint32_t sampleRate,
uint32_t channelCount,
audio_format_t format,
@@ -429,9 +430,9 @@
}
std::string directory;
- status_t status = clean(&directory);
+ const status_t status = clean(&directory);
if (status != NO_ERROR) return status;
- std::string dirPrefix = directory + "/";
+ const std::string dirPrefix = directory + "/";
const std::string path = dirPrefix + filename;
@@ -503,7 +504,7 @@
// Success: add our name to managed files.
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
// weak synchronization - only update mFiles if the directory hasn't changed.
if (mDirectory == directory) {
mFiles.emplace_back(filename); // add to the end to preserve sort.
diff --git a/services/audioflinger/NBAIO_Tee.h b/services/audioflinger/afutils/NBAIO_Tee.h
similarity index 96%
rename from services/audioflinger/NBAIO_Tee.h
rename to services/audioflinger/afutils/NBAIO_Tee.h
index fed8cc8..17b6175 100644
--- a/services/audioflinger/NBAIO_Tee.h
+++ b/services/audioflinger/afutils/NBAIO_Tee.h
@@ -15,8 +15,8 @@
*/
// Enabled with TEE_SINK in Configuration.h
-#ifndef ANDROID_NBAIO_TEE_H
-#define ANDROID_NBAIO_TEE_H
+
+#pragma once
#ifdef TEE_SINK
@@ -216,7 +216,7 @@
// Note: as mentioned in NBAIO_Tee::set(), don't call set() while write() is
// ongoing.
if (enabled) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
mFlags = flags;
mFormat = format; // could get this from the Sink.
mFrames = frames;
@@ -228,7 +228,7 @@
}
void setId(const std::string &id) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
mId = id;
}
@@ -237,7 +237,7 @@
std::string suffix;
NBAIO_SinkSource sinkSource;
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
suffix = mId + reason;
sinkSource = mSinkSource;
}
@@ -281,13 +281,13 @@
class RunningTees {
public:
void add(const std::shared_ptr<NBAIO_TeeImpl> &tee) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
ALOGW_IF(!mTees.emplace(tee).second,
"%s: %p already exists in mTees", __func__, tee.get());
}
void remove(const std::shared_ptr<NBAIO_TeeImpl> &tee) {
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
ALOGW_IF(mTees.erase(tee) != 1,
"%s: %p doesn't exist in mTees", __func__, tee.get());
}
@@ -295,7 +295,7 @@
void dump(int fd, const std::string &reason) {
std::vector<std::shared_ptr<NBAIO_TeeImpl>> tees; // safe snapshot of tees
{
- std::lock_guard<std::mutex> _l(mLock);
+ const std::lock_guard<std::mutex> _l(mLock);
tees.insert(tees.end(), mTees.begin(), mTees.end());
}
for (const auto &tee : tees) {
@@ -323,4 +323,3 @@
} // namespace android
#endif // TEE_SINK
-#endif // !ANDROID_NBAIO_TEE_H
diff --git a/services/audioflinger/afutils/TypedLogger.cpp b/services/audioflinger/afutils/TypedLogger.cpp
new file mode 100644
index 0000000..7c546a5
--- /dev/null
+++ b/services/audioflinger/afutils/TypedLogger.cpp
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2017, 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 "AudioFlinger"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <pthread.h>
+#include "TypedLogger.h"
+
+namespace android::aflog {
+
+// External linkage access of thread local storage outside of this shared library
+// causes orphaned memory allocations. This occurs in the implementation of
+// __emutls_get_address(), see b/284657986.
+//
+// We only expose a thread local storage getter and setter here, not the
+// actual thread local variable.
+
+namespace {
+thread_local NBLog::Writer *tlNBLogWriter;
+} // namespace
+
+NBLog::Writer *getThreadWriter() {
+ return tlNBLogWriter;
+}
+
+void setThreadWriter(NBLog::Writer *writer) {
+ tlNBLogWriter = writer;
+}
+
+} // namespace android::aflog
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/afutils/TypedLogger.h
similarity index 78%
rename from services/audioflinger/TypedLogger.h
rename to services/audioflinger/afutils/TypedLogger.h
index feb71e3..8c2d239 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/afutils/TypedLogger.h
@@ -15,8 +15,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_TYPED_LOGGER_H
-#define ANDROID_TYPED_LOGGER_H
+#pragma once
// This is the client API for the typed logger.
@@ -85,56 +84,56 @@
// slower than nullptr check when logging is enabled at compile-time and disabled at runtime.
// Write formatted entry to log
-#define LOGT(fmt, ...) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOGT(fmt, ...) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->logFormat((fmt), hash(__FILE__, __LINE__), ##__VA_ARGS__); } \
while (0)
// Write histogram timestamp entry
-#define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_HIST_TS() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
// Record that audio was turned on/off
-#define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_AUDIO_STATE() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
// Log the difference bewteen frames presented by HAL and frames written to HAL output sink,
// divided by the sample rate. Parameter ms is of type double.
-#define LOG_LATENCY(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_LATENCY(ms) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_LATENCY>(ms); } while (0)
// Record thread overrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_OVERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_OVERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_OVERRUN>(ns); } while (0)
// Record thread info. This currently includes type, frameCount, and sampleRate.
// Parameter type is thread_info_t as defined in NBLog.h.
-#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = aflog::getThreadWriter(); \
if (x != nullptr) x->log<NBLog::EVENT_THREAD_INFO>(info); } while (0)
-#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = aflog::getThreadWriter(); \
if (x != nullptr) x->log<NBLog::EVENT_THREAD_PARAMS>(params); } while (0)
// Record thread underrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_UNDERRUN>(ns); } while (0)
// Record thread warmup time in milliseconds. Parameter ms is of type double.
-#define LOG_WARMUP_TIME(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WARMUP_TIME(ms) do { \
+ NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_WARMUP_TIME>(ms); } while (0)
// Record a typed entry that represents a thread's work time in nanoseconds.
// Parameter ns should be of type uint32_t.
-#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
x->log<NBLog::EVENT_WORK_TIME>(ns); } while (0)
-namespace android {
-extern "C" {
+namespace android::aflog {
// TODO consider adding a thread_local NBLog::Writer tlStubNBLogWriter and then
-// initialize below tlNBLogWriter to &tlStubNBLogWriter to remove the need to
+// initialize setThreadWriter() to &tlStubNBLogWriter to remove the need to
// check for nullptr every time. Also reduces the need to add a new logging macro above
// each time we want to log a new type.
-extern thread_local NBLog::Writer *tlNBLogWriter;
-}
-} // namespace android
-#endif // ANDROID_TYPED_LOGGER_H
+NBLog::Writer *getThreadWriter();
+void setThreadWriter(NBLog::Writer *writer);
+
+} // namespace android::aflog
diff --git a/services/audioflinger/datapath/Android.bp b/services/audioflinger/datapath/Android.bp
new file mode 100644
index 0000000..58f0422
--- /dev/null
+++ b/services/audioflinger/datapath/Android.bp
@@ -0,0 +1,64 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+audioflinger_datapath_tidy_errors = audioflinger_base_tidy_errors + [
+ "modernize-avoid-c-arrays",
+ "modernize-deprecated-headers",
+ "modernize-pass-by-value",
+ "modernize-use-auto",
+ "modernize-use-nodiscard",
+
+ // TODO(b/275642749) Reenable these warnings
+ "-misc-non-private-member-variables-in-classes",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_datapath_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: audioflinger_base_cflags,
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: audioflinger_datapath_tidy_errors,
+ tidy_checks_as_errors: audioflinger_datapath_tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
+cc_library {
+ name: "libaudioflinger_datapath",
+
+ defaults: [
+ "audioflinger_datapath_flags_defaults",
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
+ srcs: [
+ "AudioHwDevice.cpp",
+ "AudioStreamOut.cpp",
+ "SpdifStreamOut.cpp",
+ ],
+
+ header_libs: [
+ "libaudiohal_headers",
+ "liberror_headers",
+ ],
+
+ shared_libs: [
+ "audioclient-types-aidl-cpp",
+ "av-types-aidl-cpp",
+ "libaudiospdif",
+ "libaudioutils",
+ "libbase",
+ "liblog",
+ "libutils", // refbase
+ ],
+}
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/datapath/AudioHwDevice.cpp
similarity index 94%
rename from services/audioflinger/AudioHwDevice.cpp
rename to services/audioflinger/datapath/AudioHwDevice.cpp
index dee6161..9ff316c 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/datapath/AudioHwDevice.cpp
@@ -44,7 +44,7 @@
{
struct audio_config originalConfig = *config;
- AudioStreamOut *outputStream = new AudioStreamOut(this, flags);
+ auto outputStream = new AudioStreamOut(this, flags);
// Try to open the HAL first using the current format.
ALOGV("openOutputStream(), try "
@@ -57,7 +57,7 @@
if (status != NO_ERROR) {
delete outputStream;
- outputStream = NULL;
+ outputStream = nullptr;
// FIXME Look at any modification to the config.
// The HAL might modify the config to suggest a wrapped format.
@@ -71,7 +71,7 @@
status);
// If the data is encoded then try again using wrapped PCM.
- bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
+ const bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
&& ((flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)
&& ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0);
@@ -83,7 +83,7 @@
ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
status);
delete outputStream;
- outputStream = NULL;
+ outputStream = nullptr;
}
} else {
ALOGE("ERROR - openOutputStream(), SPDIFEncoder does not support format 0x%08x",
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/datapath/AudioHwDevice.h
similarity index 81%
rename from services/audioflinger/AudioHwDevice.h
rename to services/audioflinger/datapath/AudioHwDevice.h
index d071922..f9cb80e 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/datapath/AudioHwDevice.h
@@ -54,25 +54,25 @@
, mFlags(flags) { }
virtual ~AudioHwDevice() { free((void *)mModuleName); }
- bool canSetMasterVolume() const {
+ [[nodiscard]] bool canSetMasterVolume() const {
return (0 != (mFlags & AHWD_CAN_SET_MASTER_VOLUME));
}
- bool canSetMasterMute() const {
+ [[nodiscard]] bool canSetMasterMute() const {
return (0 != (mFlags & AHWD_CAN_SET_MASTER_MUTE));
}
- bool isInsert() const {
+ [[nodiscard]] bool isInsert() const {
return (0 != (mFlags & AHWD_IS_INSERT));
}
- bool supportsBluetoothVariableLatency() const {
+ [[nodiscard]] bool supportsBluetoothVariableLatency() const {
return (0 != (mFlags & AHWD_SUPPORTS_BT_LATENCY_MODES));
}
- audio_module_handle_t handle() const { return mHandle; }
- const char *moduleName() const { return mModuleName; }
- sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
+ [[nodiscard]] audio_module_handle_t handle() const { return mHandle; }
+ [[nodiscard]] const char *moduleName() const { return mModuleName; }
+ [[nodiscard]] sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
/** This method creates and opens the audio hardware output stream.
* The "address" parameter qualifies the "devices" audio device type if needed.
@@ -89,17 +89,17 @@
struct audio_config *config,
const char *address);
- bool supportsAudioPatches() const;
+ [[nodiscard]] bool supportsAudioPatches() const;
- status_t getAudioPort(struct audio_port_v7 *port) const;
+ [[nodiscard]] status_t getAudioPort(struct audio_port_v7 *port) const;
- status_t getMmapPolicyInfos(
+ [[nodiscard]] status_t getMmapPolicyInfos(
media::audio::common::AudioMMapPolicyType policyType,
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) const;
- int32_t getAAudioMixerBurstCount() const;
+ [[nodiscard]] int32_t getAAudioMixerBurstCount() const;
- int32_t getAAudioHardwareBurstMinUsec() const;
+ [[nodiscard]] int32_t getAAudioHardwareBurstMinUsec() const;
private:
const audio_module_handle_t mHandle;
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/datapath/AudioStreamOut.cpp
similarity index 86%
rename from services/audioflinger/AudioStreamOut.cpp
rename to services/audioflinger/datapath/AudioStreamOut.cpp
index 65ec0e8..6fa82e5 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/datapath/AudioStreamOut.cpp
@@ -31,21 +31,13 @@
// ----------------------------------------------------------------------------
AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)
: audioHwDev(dev)
- , stream(NULL)
, flags(flags)
- , mFramesWritten(0)
- , mFramesWrittenAtStandby(0)
- , mRenderPosition(0)
- , mRateMultiplier(1)
- , mHalFormatHasProportionalFrames(false)
- , mHalFrameSize(0)
- , mExpectRetrograde(false)
{
}
-AudioStreamOut::~AudioStreamOut()
-{
-}
+// This must be defined here together with the HAL includes above and
+// not solely in the header.
+AudioStreamOut::~AudioStreamOut() = default;
sp<DeviceHalInterface> AudioStreamOut::hwDev() const
{
@@ -54,12 +46,12 @@
status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
{
- if (stream == 0) {
+ if (stream == nullptr) {
return NO_INIT;
}
uint32_t halPosition = 0;
- status_t status = stream->getRenderPosition(&halPosition);
+ const status_t status = stream->getRenderPosition(&halPosition);
if (status != NO_ERROR) {
return status;
}
@@ -67,7 +59,7 @@
// Maintain a 64-bit render position using the 32-bit result from the HAL.
// This delta calculation relies on the arithmetic overflow behavior
// of integers. For example (100 - 0xFFFFFFF0) = 116.
- const uint32_t truncatedPosition = (uint32_t)mRenderPosition;
+ const auto truncatedPosition = (uint32_t)mRenderPosition;
int32_t deltaHalPosition; // initialization not needed, overwitten by __builtin_sub_overflow()
(void) __builtin_sub_overflow(halPosition, truncatedPosition, &deltaHalPosition);
@@ -87,7 +79,7 @@
status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
{
uint64_t position64 = 0;
- status_t status = getRenderPosition(&position64);
+ const status_t status = getRenderPosition(&position64);
if (status == NO_ERROR) {
*frames = (uint32_t)position64;
}
@@ -96,12 +88,12 @@
status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
{
- if (stream == 0) {
+ if (stream == nullptr) {
return NO_INIT;
}
uint64_t halPosition = 0;
- status_t status = stream->getPresentationPosition(&halPosition, timestamp);
+ const status_t status = stream->getPresentationPosition(&halPosition, timestamp);
if (status != NO_ERROR) {
return status;
}
@@ -109,7 +101,7 @@
// Adjust for standby using HAL rate frames.
// Only apply this correction if the HAL is getting PCM frames.
if (mHalFormatHasProportionalFrames) {
- uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
+ const uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
0 : (halPosition - mFramesWrittenAtStandby);
// Scale from HAL sample rate to application rate.
*frames = adjustedPosition / mRateMultiplier;
@@ -129,7 +121,7 @@
{
sp<StreamOutHalInterface> outStream;
- audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
+ const audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
: flags;
@@ -195,7 +187,7 @@
mExpectRetrograde = false;
mFramesWritten = 0;
mFramesWrittenAtStandby = 0;
- status_t result = stream->flush();
+ const status_t result = stream->flush();
return result != INVALID_OPERATION ? result : NO_ERROR;
}
@@ -210,7 +202,7 @@
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
size_t bytesWritten;
- status_t result = stream->write(buffer, numBytes, &bytesWritten);
+ const status_t result = stream->write(buffer, numBytes, &bytesWritten);
if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
mFramesWritten += bytesWritten / mHalFrameSize;
}
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/datapath/AudioStreamOut.h
similarity index 84%
rename from services/audioflinger/AudioStreamOut.h
rename to services/audioflinger/datapath/AudioStreamOut.h
index 82fe238..ce00f8c 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/datapath/AudioStreamOut.h
@@ -41,7 +41,7 @@
sp<StreamOutHalInterface> stream;
const audio_output_flags_t flags;
- sp<DeviceHalInterface> hwDev() const;
+ [[nodiscard]] sp<DeviceHalInterface> hwDev() const;
AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags);
@@ -78,7 +78,7 @@
/**
* @return frame size from the perspective of the application and the AudioFlinger.
*/
- virtual size_t getFrameSize() const { return mHalFrameSize; }
+ [[nodiscard]] virtual size_t getFrameSize() const { return mHalFrameSize; }
/**
* @return audio stream configuration: channel mask, format, sample rate:
@@ -88,7 +88,7 @@
* - sample rate from the perspective of the application and the AudioFlinger,
* The HAL may be running at a higher sample rate if, for example, playing wrapped EAC3.
*/
- virtual audio_config_base_t getAudioProperties() const;
+ [[nodiscard]] virtual audio_config_base_t getAudioProperties() const;
virtual status_t flush();
virtual status_t standby();
@@ -101,13 +101,13 @@
virtual void presentationComplete() { mExpectRetrograde = true; }
protected:
- uint64_t mFramesWritten; // reset by flush
- uint64_t mFramesWrittenAtStandby;
- uint64_t mRenderPosition; // reset by flush, standby, or presentation complete
- int mRateMultiplier;
- bool mHalFormatHasProportionalFrames;
- size_t mHalFrameSize;
- bool mExpectRetrograde; // see presentationComplete
+ uint64_t mFramesWritten = 0; // reset by flush
+ uint64_t mFramesWrittenAtStandby = 0;
+ uint64_t mRenderPosition = 0; // reset by flush, standby, or presentation complete
+ int mRateMultiplier = 1;
+ bool mHalFormatHasProportionalFrames = false;
+ size_t mHalFrameSize = 0;
+ bool mExpectRetrograde = false; // see presentationComplete
};
} // namespace android
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/datapath/SpdifStreamOut.cpp
similarity index 95%
rename from services/audioflinger/SpdifStreamOut.cpp
rename to services/audioflinger/datapath/SpdifStreamOut.cpp
index 0ce5681..43e9c0c 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/datapath/SpdifStreamOut.cpp
@@ -37,9 +37,6 @@
// Tell the HAL that the data will be compressed audio wrapped in a data burst.
: AudioStreamOut(dev, (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO))
, mSpdifEncoder(this, format)
- , mApplicationFormat(AUDIO_FORMAT_DEFAULT)
- , mApplicationSampleRate(0)
- , mApplicationChannelMask(AUDIO_CHANNEL_NONE)
{
}
@@ -91,7 +88,7 @@
customConfig.format,
customConfig.channel_mask);
- status_t status = AudioStreamOut::open(
+ const status_t status = AudioStreamOut::open(
handle,
devices,
&customConfig,
diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/datapath/SpdifStreamOut.h
similarity index 78%
rename from services/audioflinger/SpdifStreamOut.h
rename to services/audioflinger/datapath/SpdifStreamOut.h
index fc9bb6e..c8dc89f 100644
--- a/services/audioflinger/SpdifStreamOut.h
+++ b/services/audioflinger/datapath/SpdifStreamOut.h
@@ -39,13 +39,13 @@
SpdifStreamOut(AudioHwDevice *dev, audio_output_flags_t flags,
audio_format_t format);
- virtual ~SpdifStreamOut() { }
+ ~SpdifStreamOut() override = default;
- virtual status_t open(
+ status_t open(
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config,
- const char *address);
+ const char *address) override;
/**
* Write audio buffer to driver. Returns number of bytes written, or a
@@ -60,32 +60,34 @@
* callback function must be called when more space is available in the
* driver/hardware buffer.
*/
- virtual ssize_t write(const void* buffer, size_t bytes);
+ ssize_t write(const void* buffer, size_t bytes) override;
/**
* @return frame size from the perspective of the application and the AudioFlinger.
*/
- virtual size_t getFrameSize() const { return sizeof(int8_t); }
+ [[nodiscard]] size_t getFrameSize() const override { return sizeof(int8_t); }
/**
* @return format from the perspective of the application and the AudioFlinger.
*/
- virtual audio_format_t getFormat() const { return mApplicationFormat; }
+ [[nodiscard]] virtual audio_format_t getFormat() const { return mApplicationFormat; }
/**
* The HAL may be running at a higher sample rate if, for example, playing wrapped EAC3.
* @return sample rate from the perspective of the application and the AudioFlinger.
*/
- virtual uint32_t getSampleRate() const { return mApplicationSampleRate; }
+ [[nodiscard]] virtual uint32_t getSampleRate() const { return mApplicationSampleRate; }
/**
* The HAL is in stereo mode when playing multi-channel compressed audio over HDMI.
* @return channel mask from the perspective of the application and the AudioFlinger.
*/
- virtual audio_channel_mask_t getChannelMask() const { return mApplicationChannelMask; }
+ [[nodiscard]] virtual audio_channel_mask_t getChannelMask() const {
+ return mApplicationChannelMask;
+ }
- virtual status_t flush();
- virtual status_t standby();
+ status_t flush() override;
+ status_t standby() override;
private:
@@ -98,7 +100,7 @@
{
}
- virtual ssize_t writeOutput(const void* buffer, size_t bytes)
+ ssize_t writeOutput(const void* buffer, size_t bytes) override
{
return mSpdifStreamOut->writeDataBurst(buffer, bytes);
}
@@ -107,9 +109,9 @@
};
MySPDIFEncoder mSpdifEncoder;
- audio_format_t mApplicationFormat;
- uint32_t mApplicationSampleRate;
- audio_channel_mask_t mApplicationChannelMask;
+ audio_format_t mApplicationFormat = AUDIO_FORMAT_DEFAULT;
+ uint32_t mApplicationSampleRate = 0;
+ audio_channel_mask_t mApplicationChannelMask = AUDIO_CHANNEL_NONE;
ssize_t writeDataBurst(const void* data, size_t bytes);
ssize_t writeInternal(const void* buffer, size_t bytes);
diff --git a/services/audioflinger/ThreadMetrics.h b/services/audioflinger/datapath/ThreadMetrics.h
similarity index 100%
rename from services/audioflinger/ThreadMetrics.h
rename to services/audioflinger/datapath/ThreadMetrics.h
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/datapath/TrackMetrics.h
similarity index 100%
rename from services/audioflinger/TrackMetrics.h
rename to services/audioflinger/datapath/TrackMetrics.h
diff --git a/services/audioflinger/fastpath/Android.bp b/services/audioflinger/fastpath/Android.bp
new file mode 100644
index 0000000..84a580f
--- /dev/null
+++ b/services/audioflinger/fastpath/Android.bp
@@ -0,0 +1,75 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+// TODO(b/275642749) Reenable these warnings
+fastpath_tidy_errors = audioflinger_base_tidy_errors + [
+ "-misc-non-private-member-variables-in-classes",
+ "-performance-no-int-to-ptr",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "fastpath_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: audioflinger_base_cflags,
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: fastpath_tidy_errors,
+ tidy_checks_as_errors: fastpath_tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
+cc_library_shared {
+ name: "libaudioflinger_fastpath",
+
+ defaults: [
+ "fastpath_flags_defaults",
+ ],
+
+ srcs: [
+ "FastCapture.cpp",
+ "FastCaptureDumpState.cpp",
+ "FastCaptureState.cpp",
+ "FastMixer.cpp",
+ "FastMixerDumpState.cpp",
+ "FastMixerState.cpp",
+ "FastThread.cpp",
+ "FastThreadDumpState.cpp",
+ "FastThreadState.cpp",
+ "StateQueue.cpp",
+ ],
+
+ include_dirs: [
+ "frameworks/av/services/audioflinger", // for Configuration
+ ],
+
+ shared_libs: [
+ "libaudioflinger_utils", // NBAIO_Tee
+ "libaudioprocessing",
+ "libaudioutils",
+ "libcutils",
+ "liblog",
+ "libnbaio",
+ "libnblog", // legacy NBLog that can be removed.
+ "libutils",
+ ],
+
+ header_libs: [
+ "libaudiohal_headers",
+ "libmedia_headers",
+ ],
+
+ sanitize: {
+ integer_overflow: true,
+ },
+
+}
diff --git a/services/audioflinger/AutoPark.h b/services/audioflinger/fastpath/AutoPark.h
similarity index 94%
rename from services/audioflinger/AutoPark.h
rename to services/audioflinger/fastpath/AutoPark.h
index 83f6b7d..d71a305 100644
--- a/services/audioflinger/AutoPark.h
+++ b/services/audioflinger/fastpath/AutoPark.h
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#pragma once
+
namespace android {
// T is FastMixer or FastCapture
@@ -23,7 +25,6 @@
// Park the specific FastThread, which can be nullptr, in hot idle if not currently idling
explicit AutoPark(const sp<T>& fastThread) : mFastThread(fastThread)
{
- mPreviousCommand = FastThreadState::HOT_IDLE;
if (fastThread != nullptr) {
auto sq = mFastThread->sq();
FastThreadState *state = sq->begin();
@@ -55,7 +56,7 @@
private:
const sp<T> mFastThread;
// if !&IDLE, holds the FastThread state to restore after new parameters processed
- FastThreadState::Command mPreviousCommand;
+ FastThreadState::Command mPreviousCommand = FastThreadState::HOT_IDLE;
}; // class AutoPark
} // namespace android
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/fastpath/FastCapture.cpp
similarity index 85%
rename from services/audioflinger/FastCapture.cpp
rename to services/audioflinger/fastpath/FastCapture.cpp
index 2963202..288036d 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/fastpath/FastCapture.cpp
@@ -30,24 +30,16 @@
namespace android {
-/*static*/ const FastCaptureState FastCapture::sInitial;
+/*static*/ const FastCaptureState FastCapture::sInitial{};
-FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us"),
- mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0),
- mReadBuffer(NULL), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0),
- // mDummyDumpState
- mTotalNativeFramesRead(0)
+FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us")
{
+ // base class initialization
mPrevious = &sInitial;
mCurrent = &sInitial;
-
mDummyDumpState = &mDummyFastCaptureDumpState;
}
-FastCapture::~FastCapture()
-{
-}
-
FastCaptureStateQueue* FastCapture::sq()
{
return &mSQ;
@@ -95,11 +87,11 @@
bool eitherChanged = false;
// check for change in input HAL configuration
- NBAIO_Format previousFormat = mFormat;
+ const NBAIO_Format previousFormat = mFormat;
if (current->mInputSourceGen != mInputSourceGen) {
mInputSource = current->mInputSource;
mInputSourceGen = current->mInputSourceGen;
- if (mInputSource == NULL) {
+ if (mInputSource == nullptr) {
mFormat = Format_Invalid;
mSampleRate = 0;
} else {
@@ -122,19 +114,19 @@
}
// input source and pipe sink must be compatible
- if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) {
+ if (eitherChanged && mInputSource != nullptr && mPipeSink != nullptr) {
ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format()));
}
if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
// FIXME to avoid priority inversion, don't free here
free(mReadBuffer);
- mReadBuffer = NULL;
+ mReadBuffer = nullptr;
if (frameCount > 0 && mSampleRate > 0) {
// FIXME new may block for unbounded time at internal mutex of the heap
// implementation; it would be better to have normal capture thread allocate for
// us to avoid blocking here and to prevent possible priority inversion
- size_t bufferSize = frameCount * Format_frameSize(mFormat);
+ const size_t bufferSize = frameCount * Format_frameSize(mFormat);
(void)posix_memalign(&mReadBuffer, 32, bufferSize);
memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
mPeriodNs = (frameCount * 1000000000LL) / mSampleRate; // 1.00
@@ -166,9 +158,9 @@
AudioBufferProvider* fastPatchRecordBufferProvider = current->mFastPatchRecordBufferProvider;
AudioBufferProvider::Buffer patchBuffer;
- if (fastPatchRecordBufferProvider != 0) {
+ if (fastPatchRecordBufferProvider != nullptr) {
patchBuffer.frameCount = ~0;
- status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
+ const status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
if (status != NO_ERROR) {
frameCount = 0;
} else if (patchBuffer.frameCount < frameCount) {
@@ -179,11 +171,11 @@
}
if ((command & FastCaptureState::READ) /*&& isWarm*/) {
- ALOG_ASSERT(mInputSource != NULL);
- ALOG_ASSERT(mReadBuffer != NULL);
+ ALOG_ASSERT(mInputSource != nullptr);
+ ALOG_ASSERT(mReadBuffer != nullptr);
dumpState->mReadSequence++;
ATRACE_BEGIN("read");
- ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
+ const ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
ATRACE_END();
dumpState->mReadSequence++;
if (framesRead >= 0) {
@@ -201,8 +193,8 @@
}
if (command & FastCaptureState::WRITE) {
- ALOG_ASSERT(mPipeSink != NULL);
- ALOG_ASSERT(mReadBuffer != NULL);
+ ALOG_ASSERT(mPipeSink != nullptr);
+ ALOG_ASSERT(mReadBuffer != nullptr);
if (mReadBufferState < 0) {
memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat));
mReadBufferState = frameCount;
@@ -211,23 +203,23 @@
if (current->mSilenceCapture) {
memset(mReadBuffer, 0, mReadBufferState * Format_frameSize(mFormat));
}
- ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
+ const ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
audio_track_cblk_t* cblk = current->mCblk;
- if (fastPatchRecordBufferProvider != 0) {
+ if (fastPatchRecordBufferProvider != nullptr) {
// This indicates the fast track is a patch record, update the cblk by
// calling releaseBuffer().
memcpy_by_audio_format(patchBuffer.raw, current->mFastPatchRecordFormat,
mReadBuffer, mFormat.mFormat, framesWritten * mFormat.mChannelCount);
patchBuffer.frameCount = framesWritten;
fastPatchRecordBufferProvider->releaseBuffer(&patchBuffer);
- } else if (cblk != NULL && framesWritten > 0) {
+ } else if (cblk != nullptr && framesWritten > 0) {
// FIXME This supports at most one fast capture client.
// To handle multiple clients this could be converted to an array,
// or with a lot more work the control block could be shared by all clients.
- int32_t rear = cblk->u.mStreaming.mRear;
+ const int32_t rear = cblk->u.mStreaming.mRear;
android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
cblk->mServer += framesWritten;
- int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+ const int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
if (!(old & CBLK_FUTEX_WAKE)) {
// client is never in server process, so don't use FUTEX_WAKE_PRIVATE
(void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
diff --git a/services/audioflinger/fastpath/FastCapture.h b/services/audioflinger/fastpath/FastCapture.h
new file mode 100644
index 0000000..b565216
--- /dev/null
+++ b/services/audioflinger/fastpath/FastCapture.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "FastThread.h"
+#include "StateQueue.h"
+#include "FastCaptureState.h"
+#include "FastCaptureDumpState.h"
+
+namespace android {
+
+using FastCaptureStateQueue = StateQueue<FastCaptureState>;
+
+class FastCapture : public FastThread {
+
+public:
+ FastCapture();
+
+ FastCaptureStateQueue* sq();
+
+private:
+ FastCaptureStateQueue mSQ;
+
+ // callouts
+ const FastThreadState *poll() override;
+ void setNBLogWriter(NBLog::Writer *logWriter) override;
+ void onIdle() override;
+ void onExit() override;
+ bool isSubClassCommand(FastThreadState::Command command) override;
+ void onStateChange() override;
+ void onWork() override;
+
+ static const FastCaptureState sInitial;
+
+ FastCaptureState mPreIdle; // copy of state before we went into idle
+ // FIXME by renaming, could pull up many of these to FastThread
+ NBAIO_Source* mInputSource = nullptr;
+ int mInputSourceGen = 0;
+ NBAIO_Sink* mPipeSink = nullptr;
+ int mPipeSinkGen = 0;
+ void* mReadBuffer = nullptr;
+ ssize_t mReadBufferState = -1; // number of initialized frames in readBuffer,
+ // or -1 to clear
+ NBAIO_Format mFormat = Format_Invalid;
+ unsigned mSampleRate = 0;
+ FastCaptureDumpState mDummyFastCaptureDumpState;
+ uint32_t mTotalNativeFramesRead = 0; // copied to dumpState->mFramesRead
+
+}; // class FastCapture
+
+} // namespace android
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
similarity index 82%
rename from services/audioflinger/FastCaptureDumpState.cpp
rename to services/audioflinger/fastpath/FastCaptureDumpState.cpp
index 243dfa5..fe7ea16 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
@@ -24,24 +24,15 @@
namespace android {
-FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
- mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
-{
-}
-
-FastCaptureDumpState::~FastCaptureDumpState()
-{
-}
-
void FastCaptureDumpState::dump(int fd) const
{
if (mCommand == FastCaptureState::INITIAL) {
dprintf(fd, " FastCapture not initialized\n");
return;
}
- double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+ const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
(mMeasuredWarmupTs.tv_nsec / 1000000.0);
- double periodSec = (double) mFrameCount / mSampleRate;
+ const double periodSec = (double) mFrameCount / mSampleRate;
dprintf(fd, " FastCapture command=%s readSequence=%u framesRead=%u\n"
" readErrors=%u sampleRate=%u frameCount=%zu\n"
" measuredWarmup=%.3g ms, warmupCycles=%u period=%.2f ms\n"
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/fastpath/FastCaptureDumpState.h
similarity index 67%
rename from services/audioflinger/FastCaptureDumpState.h
rename to services/audioflinger/fastpath/FastCaptureDumpState.h
index 34ce456..3dc8a9b 100644
--- a/services/audioflinger/FastCaptureDumpState.h
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.h
@@ -14,30 +14,28 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+#pragma once
#include <stdint.h>
+#include <type_traits>
#include "Configuration.h"
#include "FastThreadDumpState.h"
namespace android {
struct FastCaptureDumpState : FastThreadDumpState {
- FastCaptureDumpState();
- /*virtual*/ ~FastCaptureDumpState();
-
void dump(int fd) const; // should only be called on a stable copy, not the original
// FIXME by renaming, could pull up many of these to FastThreadDumpState
- uint32_t mReadSequence; // incremented before and after each read()
- uint32_t mFramesRead; // total number of frames read successfully
- uint32_t mReadErrors; // total number of read() errors
- uint32_t mSampleRate;
- size_t mFrameCount;
+ uint32_t mReadSequence = 0; // incremented before and after each read()
+ uint32_t mFramesRead = 0; // total number of frames read successfully
+ uint32_t mReadErrors = 0; // total number of read() errors
+ uint32_t mSampleRate = 0;
+ size_t mFrameCount = 0;
bool mSilenced = false; // capture is silenced
};
-} // namespace android
+// No virtuals
+static_assert(!std::is_polymorphic_v<FastCaptureDumpState>);
-#endif // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+} // namespace android
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/fastpath/FastCaptureState.cpp
similarity index 80%
rename from services/audioflinger/FastCaptureState.cpp
rename to services/audioflinger/fastpath/FastCaptureState.cpp
index 918ba9c..77c0c4c 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureState.cpp
@@ -18,20 +18,11 @@
namespace android {
-FastCaptureState::FastCaptureState() : FastThreadState(),
- mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0), mFrameCount(0)
-{
-}
-
-FastCaptureState::~FastCaptureState()
-{
-}
-
// static
const char *FastCaptureState::commandToString(Command command)
{
const char *str = FastThreadState::commandToString(command);
- if (str != NULL) {
+ if (str != nullptr) {
return str;
}
switch (command) {
@@ -39,7 +30,7 @@
case FastCaptureState::WRITE: return "WRITE";
case FastCaptureState::READ_WRITE: return "READ_WRITE";
}
- LOG_ALWAYS_FATAL("%s", __func__);
+ LOG_ALWAYS_FATAL("%s: command %d invalid", __func__, (int) command);
}
} // namespace android
diff --git a/services/audioflinger/FastCaptureState.h b/services/audioflinger/fastpath/FastCaptureState.h
similarity index 76%
rename from services/audioflinger/FastCaptureState.h
rename to services/audioflinger/fastpath/FastCaptureState.h
index f949275..0f4126e 100644
--- a/services/audioflinger/FastCaptureState.h
+++ b/services/audioflinger/fastpath/FastCaptureState.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+#pragma once
+#include <type_traits>
#include <media/nbaio/NBAIO.h>
#include <media/AudioBufferProvider.h>
#include "FastThreadState.h"
@@ -26,16 +26,14 @@
// Represent a single state of the fast capture
struct FastCaptureState : FastThreadState {
- FastCaptureState();
- /*virtual*/ ~FastCaptureState();
-
// all pointer fields use raw pointers; objects are owned and ref-counted by RecordThread
- NBAIO_Source* mInputSource; // HAL input device, must already be negotiated
+ NBAIO_Source* mInputSource = nullptr; // HAL input device, must already be negotiated
// FIXME by renaming, could pull up these fields to FastThreadState
- int mInputSourceGen; // increment when mInputSource is assigned
- NBAIO_Sink* mPipeSink; // after reading from input source, write to this pipe sink
- int mPipeSinkGen; // increment when mPipeSink is assigned
- size_t mFrameCount; // number of frames per fast capture buffer
+ int mInputSourceGen = 0; // increment when mInputSource is assigned
+ NBAIO_Sink* mPipeSink = nullptr; // after reading from input source,
+ // write to this pipe sink
+ int mPipeSinkGen = 0; // increment when mPipeSink is assigned
+ size_t mFrameCount = 0; // number of frames per fast capture buffer
audio_track_cblk_t* mCblk; // control block for the single fast client, or NULL
audio_format_t mFastPatchRecordFormat = AUDIO_FORMAT_INVALID;
@@ -55,6 +53,7 @@
static const char *commandToString(Command command);
}; // struct FastCaptureState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastCaptureState>);
-#endif // ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+} // namespace android
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/fastpath/FastMixer.cpp
similarity index 93%
rename from services/audioflinger/FastMixer.cpp
rename to services/audioflinger/fastpath/FastMixer.cpp
index 61dd3f2..e0a15c1 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/fastpath/FastMixer.cpp
@@ -42,7 +42,7 @@
#include <cutils/bitops.h>
#include <media/AudioMixer.h>
#include "FastMixer.h"
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
namespace android {
@@ -61,48 +61,25 @@
: FastThread("cycle_ms", "load_us"),
// mFastTrackNames
// mGenerations
- mOutputSink(NULL),
- mOutputSinkGen(0),
- mMixer(NULL),
- mSinkBuffer(NULL),
- mSinkBufferSize(0),
- mSinkChannelCount(FCC_2),
- mMixerBuffer(NULL),
- mMixerBufferSize(0),
- mMixerBufferState(UNDEFINED),
- mFormat(Format_Invalid),
- mSampleRate(0),
- mFastTracksGen(0),
- mTotalNativeFramesWritten(0),
// timestamp
- mNativeFramesWrittenButNotPresented(0), // the = 0 is to silence the compiler
- mMasterMono(false),
mThreadIoHandle(parentIoHandle)
{
// FIXME pass sInitial as parameter to base class constructor, and make it static local
mPrevious = &sInitial;
mCurrent = &sInitial;
-
mDummyDumpState = &mDummyFastMixerDumpState;
+
// TODO: Add channel mask to NBAIO_Format.
// We assume that the channel mask must be a valid positional channel mask.
mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
mBalance.setChannelMask(mSinkChannelMask);
- unsigned i;
- for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
- mGenerations[i] = 0;
- }
#ifdef FAST_THREAD_STATISTICS
mOldLoad.tv_sec = 0;
mOldLoad.tv_nsec = 0;
#endif
}
-FastMixer::~FastMixer()
-{
-}
-
FastMixerStateQueue* FastMixer::sq()
{
return &mSQ;
@@ -229,13 +206,13 @@
unsigned previousTrackMask;
// check for change in output HAL configuration
- NBAIO_Format previousFormat = mFormat;
+ const NBAIO_Format previousFormat = mFormat;
if (current->mOutputSinkGen != mOutputSinkGen) {
mOutputSink = current->mOutputSink;
mOutputSinkGen = current->mOutputSinkGen;
mSinkChannelMask = current->mSinkChannelMask;
mBalance.setChannelMask(mSinkChannelMask);
- if (mOutputSink == NULL) {
+ if (mOutputSink == nullptr) {
mFormat = Format_Invalid;
mSampleRate = 0;
mSinkChannelCount = 0;
@@ -259,11 +236,11 @@
if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
// FIXME to avoid priority inversion, don't delete here
delete mMixer;
- mMixer = NULL;
+ mMixer = nullptr;
free(mMixerBuffer);
- mMixerBuffer = NULL;
+ mMixerBuffer = nullptr;
free(mSinkBuffer);
- mSinkBuffer = NULL;
+ mSinkBuffer = nullptr;
if (frameCount > 0 && mSampleRate > 0) {
// FIXME new may block for unbounded time at internal mutex of the heap
// implementation; it would be better to have normal mixer allocate for us
@@ -320,7 +297,7 @@
// process removed tracks first to avoid running out of track names
unsigned removedTracks = previousTrackMask & ~currentTrackMask;
while (removedTracks != 0) {
- int i = __builtin_ctz(removedTracks);
+ const int i = __builtin_ctz(removedTracks);
removedTracks &= ~(1 << i);
updateMixerTrack(i, REASON_REMOVE);
// don't reset track dump state, since other side is ignoring it
@@ -329,7 +306,7 @@
// now process added tracks
unsigned addedTracks = currentTrackMask & ~previousTrackMask;
while (addedTracks != 0) {
- int i = __builtin_ctz(addedTracks);
+ const int i = __builtin_ctz(addedTracks);
addedTracks &= ~(1 << i);
updateMixerTrack(i, REASON_ADD);
}
@@ -338,7 +315,7 @@
// but may have a different buffer provider or volume provider
unsigned modifiedTracks = currentTrackMask & previousTrackMask;
while (modifiedTracks != 0) {
- int i = __builtin_ctz(modifiedTracks);
+ const int i = __builtin_ctz(modifiedTracks);
modifiedTracks &= ~(1 << i);
updateMixerTrack(i, REASON_MODIFY);
}
@@ -373,8 +350,8 @@
const FastMixerState::Command command = mCommand;
const size_t frameCount = current->mFrameCount;
- if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
- ALOG_ASSERT(mMixerBuffer != NULL);
+ if ((command & FastMixerState::MIX) && (mMixer != nullptr) && mIsWarm) {
+ ALOG_ASSERT(mMixerBuffer != nullptr);
// AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
// so we keep a side copy of enabledTracks
@@ -383,7 +360,7 @@
// for each track, update volume and check for underrun
unsigned currentTrackMask = current->mTrackMask;
while (currentTrackMask != 0) {
- int i = __builtin_ctz(currentTrackMask);
+ const int i = __builtin_ctz(currentTrackMask);
currentTrackMask &= ~(1 << i);
const FastTrack* fastTrack = ¤t->mFastTracks[i];
@@ -406,8 +383,8 @@
fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
const int name = i;
- if (fastTrack->mVolumeProvider != NULL) {
- gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
+ if (fastTrack->mVolumeProvider != nullptr) {
+ const gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
@@ -418,7 +395,7 @@
// takes a tryLock, which can block
// up to 1 ms. If enough active tracks all blocked in sequence, this would result
// in the overall fast mix cycle being delayed. Should use a non-blocking FIFO.
- size_t framesReady = fastTrack->mBufferProvider->framesReady();
+ const size_t framesReady = fastTrack->mBufferProvider->framesReady();
if (ATRACE_ENABLED()) {
// I wish we had formatted trace names
char traceName[16];
@@ -464,7 +441,8 @@
mMixerBufferState = UNDEFINED;
}
//bool didFullWrite = false; // dumpsys could display a count of partial writes
- if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) {
+ if ((command & FastMixerState::WRITE)
+ && (mOutputSink != nullptr) && (mMixerBuffer != nullptr)) {
if (mMixerBufferState == UNDEFINED) {
memset(mMixerBuffer, 0, mMixerBufferSize);
mMixerBufferState = ZEROED;
@@ -481,7 +459,7 @@
mBalance.process((float *)mMixerBuffer, frameCount);
// prepare the buffer used to write to sink
- void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
+ void *buffer = mSinkBuffer != nullptr ? mSinkBuffer : mMixerBuffer;
if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
frameCount * Format_channelCount(mFormat));
@@ -493,7 +471,7 @@
audio_bytes_per_sample(mFormat.mFormat),
frameCount * audio_bytes_per_frame(mAudioChannelCount, mFormat.mFormat));
}
- // if non-NULL, then duplicate write() to this non-blocking sink
+ // if non-nullptr, then duplicate write() to this non-blocking sink
#ifdef TEE_SINK
mTee.write(buffer, frameCount);
#endif
@@ -501,7 +479,7 @@
// but this code should be modified to handle both non-blocking and blocking sinks
dumpState->mWriteSequence++;
ATRACE_BEGIN("write");
- ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
+ const ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
ATRACE_END();
dumpState->mWriteSequence++;
if (framesWritten >= 0) {
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/fastpath/FastMixer.h
similarity index 66%
rename from services/audioflinger/FastMixer.h
rename to services/audioflinger/fastpath/FastMixer.h
index d71519f..6e48df6 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/fastpath/FastMixer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_MIXER_H
-#define ANDROID_AUDIO_FAST_MIXER_H
+#pragma once
#include <atomic>
#include <audio_utils/Balance.h>
@@ -23,13 +22,13 @@
#include "StateQueue.h"
#include "FastMixerState.h"
#include "FastMixerDumpState.h"
-#include "NBAIO_Tee.h"
+#include <afutils/NBAIO_Tee.h>
namespace android {
class AudioMixer;
-typedef StateQueue<FastMixerState> FastMixerStateQueue;
+using FastMixerStateQueue = StateQueue<FastMixerState>;
class FastMixer : public FastThread {
@@ -37,7 +36,6 @@
/** FastMixer constructor takes as param the parent MixerThread's io handle (id)
for purposes of identification. */
explicit FastMixer(audio_io_handle_t threadIoHandle);
- virtual ~FastMixer();
FastMixerStateQueue* sq();
@@ -51,13 +49,13 @@
FastMixerStateQueue mSQ;
// callouts
- virtual const FastThreadState *poll();
- virtual void setNBLogWriter(NBLog::Writer *logWriter);
- virtual void onIdle();
- virtual void onExit();
- virtual bool isSubClassCommand(FastThreadState::Command command);
- virtual void onStateChange();
- virtual void onWork();
+ const FastThreadState *poll() override;
+ void setNBLogWriter(NBLog::Writer *logWriter) override;
+ void onIdle() override;
+ void onExit() override;
+ bool isSubClassCommand(FastThreadState::Command command) override;
+ void onStateChange() override;
+ void onWork() override;
enum Reason {
REASON_REMOVE,
@@ -71,41 +69,42 @@
static const FastMixerState sInitial;
FastMixerState mPreIdle; // copy of state before we went into idle
- int mGenerations[FastMixerState::kMaxFastTracks];
+ int mGenerations[FastMixerState::kMaxFastTracks]{};
// last observed mFastTracks[i].mGeneration
- NBAIO_Sink* mOutputSink;
- int mOutputSinkGen;
- AudioMixer* mMixer;
+ NBAIO_Sink* mOutputSink = nullptr;
+ int mOutputSinkGen = 0;
+ AudioMixer* mMixer = nullptr;
// mSinkBuffer audio format is stored in format.mFormat.
- void* mSinkBuffer; // used for mixer output format translation
+ void* mSinkBuffer = nullptr; // used for mixer output format translation
// if sink format is different than mixer output.
- size_t mSinkBufferSize;
- uint32_t mSinkChannelCount;
- audio_channel_mask_t mSinkChannelMask;
- void* mMixerBuffer; // mixer output buffer.
- size_t mMixerBufferSize;
+ size_t mSinkBufferSize = 0;
+ uint32_t mSinkChannelCount = FCC_2;
+ audio_channel_mask_t mSinkChannelMask; // set in ctor
+ void* mMixerBuffer = nullptr; // mixer output buffer.
+ size_t mMixerBufferSize = 0;
static constexpr audio_format_t mMixerBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
- uint32_t mAudioChannelCount; // audio channel count, excludes haptic channels.
+ // audio channel count, excludes haptic channels. Set in onStateChange().
+ uint32_t mAudioChannelCount = 0;
- enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState;
- NBAIO_Format mFormat;
- unsigned mSampleRate;
- int mFastTracksGen;
+ enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState = UNDEFINED;
+ NBAIO_Format mFormat{Format_Invalid};
+ unsigned mSampleRate = 0;
+ int mFastTracksGen = 0;
FastMixerDumpState mDummyFastMixerDumpState;
- int64_t mTotalNativeFramesWritten; // copied to dumpState->mFramesWritten
+ int64_t mTotalNativeFramesWritten = 0; // copied to dumpState->mFramesWritten
// next 2 fields are valid only when timestampStatus == NO_ERROR
ExtendedTimestamp mTimestamp;
- int64_t mNativeFramesWrittenButNotPresented;
+ int64_t mNativeFramesWrittenButNotPresented = 0;
audio_utils::Balance mBalance;
// accessed without lock between multiple threads.
- std::atomic_bool mMasterMono;
+ std::atomic_bool mMasterMono{};
std::atomic<float> mMasterBalance{};
- std::atomic_int_fast64_t mBoottimeOffset;
+ std::atomic_int_fast64_t mBoottimeOffset{};
// parent thread id for debugging purposes
[[maybe_unused]] const audio_io_handle_t mThreadIoHandle;
@@ -115,5 +114,3 @@
}; // class FastMixer
} // namespace android
-
-#endif // ANDROID_AUDIO_FAST_MIXER_H
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/fastpath/FastMixerDumpState.cpp
similarity index 90%
rename from services/audioflinger/FastMixerDumpState.cpp
rename to services/audioflinger/fastpath/FastMixerDumpState.cpp
index d041882..4f79dd6 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/fastpath/FastMixerDumpState.cpp
@@ -29,23 +29,11 @@
namespace android {
-FastMixerDumpState::FastMixerDumpState() : FastThreadDumpState(),
- mWriteSequence(0), mFramesWritten(0),
- mNumTracks(0), mWriteErrors(0),
- mSampleRate(0), mFrameCount(0),
- mTrackMask(0)
-{
-}
-
-FastMixerDumpState::~FastMixerDumpState()
-{
-}
-
// helper function called by qsort()
static int compare_uint32_t(const void *pa, const void *pb)
{
- uint32_t a = *(const uint32_t *)pa;
- uint32_t b = *(const uint32_t *)pb;
+ const uint32_t a = *(const uint32_t *)pa;
+ const uint32_t b = *(const uint32_t *)pb;
if (a < b) {
return -1;
} else if (a > b) {
@@ -61,9 +49,9 @@
dprintf(fd, " FastMixer not initialized\n");
return;
}
- double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+ const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
(mMeasuredWarmupTs.tv_nsec / 1000000.0);
- double mixPeriodSec = (double) mFrameCount / mSampleRate;
+ const double mixPeriodSec = (double) mFrameCount / mSampleRate;
dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
" numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
" sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
@@ -99,16 +87,16 @@
// the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the
// sample set, we get 99.8% combined, or close to three standard deviations.
static const uint32_t kTailDenominator = 1000;
- uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
+ uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : nullptr;
// loop over all the samples
for (uint32_t j = 0; j < n; ++j) {
- size_t i = oldestClosed++ & (mSamplingN - 1);
- uint32_t wallNs = mMonotonicNs[i];
- if (tail != NULL) {
+ const size_t i = oldestClosed++ & (mSamplingN - 1);
+ const uint32_t wallNs = mMonotonicNs[i];
+ if (tail != nullptr) {
tail[j] = wallNs;
}
wall.add(wallNs);
- uint32_t sampleLoadNs = mLoadNs[i];
+ const uint32_t sampleLoadNs = mLoadNs[i];
loadNs.add(sampleLoadNs);
#ifdef CPU_FREQUENCY_STATISTICS
uint32_t sampleCpukHz = mCpukHz[i];
@@ -146,10 +134,10 @@
" mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
loadMHz.getMean(), loadMHz.getMin(), loadMHz.getMax(), loadMHz.getStdDev());
#endif
- if (tail != NULL) {
+ if (tail != nullptr) {
qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
// assume same number of tail samples on each side, left and right
- uint32_t count = n / kTailDenominator;
+ const uint32_t count = n / kTailDenominator;
audio_utils::Statistics<double> left, right;
for (uint32_t i = 0; i < count; ++i) {
left.add(tail[i]);
@@ -175,7 +163,7 @@
FastMixerState::sMaxFastTracks, trackMask);
dprintf(fd, " Index Active Full Partial Empty Recent Ready Written\n");
for (uint32_t i = 0; i < FastMixerState::sMaxFastTracks; ++i, trackMask >>= 1) {
- bool isActive = trackMask & 1;
+ const bool isActive = trackMask & 1;
const FastTrackDump *ftDump = &mTracks[i];
const FastTrackUnderruns& underruns = ftDump->mUnderruns;
const char *mostRecent;
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/fastpath/FastMixerDumpState.h
similarity index 74%
rename from services/audioflinger/FastMixerDumpState.h
rename to services/audioflinger/fastpath/FastMixerDumpState.h
index 294ef78..4d2e1a0 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/fastpath/FastMixerDumpState.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+#pragma once
#include <stdint.h>
+#include <type_traits>
#include <audio_utils/TimestampVerifier.h>
#include "Configuration.h"
#include "FastThreadDumpState.h"
@@ -54,33 +54,32 @@
// Represents the dump state of a fast track
struct FastTrackDump {
- FastTrackDump() : mFramesReady(0) { }
- /*virtual*/ ~FastTrackDump() { }
FastTrackUnderruns mUnderruns;
- size_t mFramesReady; // most recent value only; no long-term statistics kept
- int64_t mFramesWritten; // last value from track
+ size_t mFramesReady = 0; // most recent value only; no long-term statistics kept
+ int64_t mFramesWritten = 0; // last value from track
};
-struct FastMixerDumpState : FastThreadDumpState {
- FastMixerDumpState();
- /*virtual*/ ~FastMixerDumpState();
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrackDump>);
+struct FastMixerDumpState : FastThreadDumpState {
void dump(int fd) const; // should only be called on a stable copy, not the original
- double mLatencyMs = 0.; // measured latency, default of 0 if no valid timestamp read.
- uint32_t mWriteSequence; // incremented before and after each write()
- uint32_t mFramesWritten; // total number of frames written successfully
- uint32_t mNumTracks; // total number of active fast tracks
- uint32_t mWriteErrors; // total number of write() errors
- uint32_t mSampleRate;
- size_t mFrameCount;
- uint32_t mTrackMask; // mask of active tracks
+ double mLatencyMs = 0.; // measured latency, default of 0 if no valid timestamp read.
+ uint32_t mWriteSequence = 0; // incremented before and after each write()
+ uint32_t mFramesWritten = 0; // total number of frames written successfully
+ uint32_t mNumTracks = 0; // total number of active fast tracks
+ uint32_t mWriteErrors = 0; // total number of write() errors
+ uint32_t mSampleRate = 0;
+ size_t mFrameCount = 0;
+ uint32_t mTrackMask = 0; // mask of active tracks
FastTrackDump mTracks[FastMixerState::kMaxFastTracks];
// For timestamp statistics.
TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
};
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerDumpState>);
-#endif // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+} // namespace android
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/fastpath/FastMixerState.cpp
similarity index 73%
rename from services/audioflinger/FastMixerState.cpp
rename to services/audioflinger/fastpath/FastMixerState.cpp
index b98842d..4fe2d86 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/fastpath/FastMixerState.cpp
@@ -22,31 +22,14 @@
namespace android {
-FastTrack::FastTrack() :
- mBufferProvider(NULL), mVolumeProvider(NULL),
- mChannelMask(AUDIO_CHANNEL_OUT_STEREO), mFormat(AUDIO_FORMAT_INVALID), mGeneration(0)
+FastMixerState::FastMixerState() : FastThreadState()
{
-}
-
-FastTrack::~FastTrack()
-{
-}
-
-FastMixerState::FastMixerState() : FastThreadState(),
- // mFastTracks
- mFastTracksGen(0), mTrackMask(0), mOutputSink(NULL), mOutputSinkGen(0),
- mFrameCount(0)
-{
- int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
+ const int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
if (ok != 0) {
ALOGE("%s pthread_once failed: %d", __func__, ok);
}
}
-FastMixerState::~FastMixerState()
-{
-}
-
// static
unsigned FastMixerState::sMaxFastTracks = kDefaultFastTracks;
@@ -57,7 +40,7 @@
const char *FastMixerState::commandToString(Command command)
{
const char *str = FastThreadState::commandToString(command);
- if (str != NULL) {
+ if (str != nullptr) {
return str;
}
switch (command) {
@@ -72,9 +55,9 @@
void FastMixerState::sMaxFastTracksInit()
{
char value[PROPERTY_VALUE_MAX];
- if (property_get("ro.audio.max_fast_tracks", value, NULL) > 0) {
+ if (property_get("ro.audio.max_fast_tracks", value, nullptr /* default_value */) > 0) {
char *endptr;
- unsigned long ul = strtoul(value, &endptr, 0);
+ const auto ul = strtoul(value, &endptr, 0);
if (*endptr == '\0' && kMinFastTracks <= ul && ul <= kMaxFastTracks) {
sMaxFastTracks = (unsigned) ul;
}
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/fastpath/FastMixerState.h
similarity index 66%
rename from services/audioflinger/FastMixerState.h
rename to services/audioflinger/fastpath/FastMixerState.h
index ce3cc14..c70e42a 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/fastpath/FastMixerState.h
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_STATE_H
+#pragma once
#include <math.h>
+#include <type_traits>
#include <audio_utils/minifloat.h>
#include <system/audio.h>
@@ -37,45 +37,50 @@
// The provider implementation is responsible for validating that the return value is in range.
virtual gain_minifloat_packed_t getVolumeLR() = 0;
protected:
- VolumeProvider() { }
- virtual ~VolumeProvider() { }
+ VolumeProvider() = default;
+ virtual ~VolumeProvider() = default;
};
// Represents the state of a fast track
struct FastTrack {
- FastTrack();
- /*virtual*/ ~FastTrack();
+ // must be nullptr if inactive, or non-nullptr if active
+ ExtendedAudioBufferProvider* mBufferProvider = nullptr;
- ExtendedAudioBufferProvider* mBufferProvider; // must be NULL if inactive, or non-NULL if active
- VolumeProvider* mVolumeProvider; // optional; if NULL then full-scale
- audio_channel_mask_t mChannelMask; // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
- audio_format_t mFormat; // track format
- int mGeneration; // increment when any field is assigned
+ // optional: if nullptr then full-scale
+ VolumeProvider* mVolumeProvider = nullptr;
+
+ // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
+ audio_channel_mask_t mChannelMask = AUDIO_CHANNEL_OUT_STEREO;
+ audio_format_t mFormat = AUDIO_FORMAT_INVALID; // track format
+ int mGeneration = 0; // increment when any field is assigned
bool mHapticPlaybackEnabled = false; // haptic playback is enabled or not
os::HapticScale mHapticIntensity = os::HapticScale::MUTE; // intensity of haptic data
float mHapticMaxAmplitude = NAN; // max amplitude allowed for haptic data
};
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrack>);
+
// Represents a single state of the fast mixer
struct FastMixerState : FastThreadState {
- FastMixerState();
- /*virtual*/ ~FastMixerState();
+ FastMixerState();
// These are the minimum, maximum, and default values for maximum number of fast tracks
- static const unsigned kMinFastTracks = 2;
- static const unsigned kMaxFastTracks = 32;
- static const unsigned kDefaultFastTracks = 8;
+ static constexpr unsigned kMinFastTracks = 2;
+ static constexpr unsigned kMaxFastTracks = 32;
+ static constexpr unsigned kDefaultFastTracks = 8;
static unsigned sMaxFastTracks; // Configured maximum number of fast tracks
static pthread_once_t sMaxFastTracksOnce; // Protects initializer for sMaxFastTracks
// all pointer fields use raw pointers; objects are owned and ref-counted by the normal mixer
FastTrack mFastTracks[kMaxFastTracks];
- int mFastTracksGen; // increment when any mFastTracks[i].mGeneration is incremented
- unsigned mTrackMask; // bit i is set if and only if mFastTracks[i] is active
- NBAIO_Sink* mOutputSink; // HAL output device, must already be negotiated
- int mOutputSinkGen; // increment when mOutputSink is assigned
- size_t mFrameCount; // number of frames per fast mix buffer
+ int mFastTracksGen = 0; // increment when any
+ // mFastTracks[i].mGeneration is incremented
+ unsigned mTrackMask = 0; // bit i is set if and only if mFastTracks[i] is active
+ NBAIO_Sink* mOutputSink = nullptr; // HAL output device, must already be negotiated
+ int mOutputSinkGen = 0; // increment when mOutputSink is assigned
+ size_t mFrameCount = 0; // number of frames per fast mix buffer
audio_channel_mask_t mSinkChannelMask; // If not AUDIO_CHANNEL_NONE, specifies sink channel
// mask when it cannot be directly calculated from
// channel count
@@ -95,6 +100,7 @@
}; // struct FastMixerState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerState>);
-#endif // ANDROID_AUDIO_FAST_MIXER_STATE_H
+} // namespace android
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/fastpath/FastThread.cpp
similarity index 87%
rename from services/audioflinger/FastThread.cpp
rename to services/audioflinger/fastpath/FastThread.cpp
index 47fe0b3..d054d71 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/fastpath/FastThread.cpp
@@ -28,7 +28,7 @@
#include <utils/Trace.h>
#include "FastThread.h"
#include "FastThreadDumpState.h"
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
#define FAST_DEFAULT_NS 999999999L // ~1 sec: default time to sleep
#define FAST_HOT_IDLE_NS 1000000L // 1 ms: time to sleep while hot idling
@@ -38,69 +38,28 @@
namespace android {
-FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/),
- // re-initialized to &sInitial by subclass constructor
- mPrevious(NULL), mCurrent(NULL),
- /* mOldTs({0, 0}), */
- mOldTsValid(false),
- mSleepNs(-1),
- mPeriodNs(0),
- mUnderrunNs(0),
- mOverrunNs(0),
- mForceNs(0),
- mWarmupNsMin(0),
- mWarmupNsMax(LONG_MAX),
- // re-initialized to &mDummySubclassDumpState by subclass constructor
- mDummyDumpState(NULL),
- mDumpState(NULL),
- mIgnoreNextOverrun(true),
-#ifdef FAST_THREAD_STATISTICS
- // mOldLoad
- mOldLoadValid(false),
- mBounds(0),
- mFull(false),
- // mTcu
-#endif
- mColdGen(0),
- mIsWarm(false),
- /* mMeasuredWarmupTs({0, 0}), */
- mWarmupCycles(0),
- mWarmupConsecutiveInRangeCycles(0),
- mTimestampStatus(INVALID_OPERATION),
-
- mCommand(FastThreadState::INITIAL),
-#if 0
- frameCount(0),
-#endif
- mAttemptedWrite(false)
- // mCycleMs(cycleMs)
- // mLoadUs(loadUs)
+FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/)
{
- mOldTs.tv_sec = 0;
- mOldTs.tv_nsec = 0;
- mMeasuredWarmupTs.tv_sec = 0;
- mMeasuredWarmupTs.tv_nsec = 0;
strlcpy(mCycleMs, cycleMs, sizeof(mCycleMs));
strlcpy(mLoadUs, loadUs, sizeof(mLoadUs));
}
-FastThread::~FastThread()
-{
-}
-
bool FastThread::threadLoop()
{
// LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
// so this initialization permits a future change to remove the check for nullptr.
- tlNBLogWriter = mDummyNBLogWriter.get();
+ aflog::setThreadWriter(mDummyNBLogWriter.get());
for (;;) {
// either nanosleep, sched_yield, or busy wait
if (mSleepNs >= 0) {
if (mSleepNs > 0) {
ALOG_ASSERT(mSleepNs < 1000000000);
- const struct timespec req = {0, mSleepNs};
- nanosleep(&req, NULL);
+ const struct timespec req = {
+ 0, // tv_sec
+ static_cast<long>(mSleepNs) // NOLINT(google-runtime-int)
+ };
+ nanosleep(&req, nullptr);
} else {
sched_yield();
}
@@ -110,7 +69,7 @@
// poll for state change
const FastThreadState *next = poll();
- if (next == NULL) {
+ if (next == nullptr) {
// continue to use the default initial state until a real state is available
// FIXME &sInitial not available, should save address earlier
//ALOG_ASSERT(mCurrent == &sInitial && previous == &sInitial);
@@ -121,10 +80,11 @@
if (next != mCurrent) {
// As soon as possible of learning of a new dump area, start using it
- mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
- tlNBLogWriter = next->mNBLogWriter != NULL ?
+ mDumpState = next->mDumpState != nullptr ? next->mDumpState : mDummyDumpState;
+ NBLog::Writer * const writer = next->mNBLogWriter != nullptr ?
next->mNBLogWriter : mDummyNBLogWriter.get();
- setNBLogWriter(tlNBLogWriter); // This is used for debugging only
+ aflog::setThreadWriter(writer);
+ setNBLogWriter(writer); // This is used for debugging only
// We want to always have a valid reference to the previous (non-idle) state.
// However, the state queue only guarantees access to current and previous states.
@@ -149,7 +109,7 @@
mCurrent = next;
}
#if !LOG_NDEBUG
- next = NULL; // not referenced again
+ next = nullptr; // not referenced again
#endif
mDumpState->mCommand = mCommand;
@@ -167,12 +127,12 @@
// FIXME consider checking previous state and only perform if previous != COLD_IDLE
if (mCurrent->mColdGen != mColdGen) {
int32_t *coldFutexAddr = mCurrent->mColdFutexAddr;
- ALOG_ASSERT(coldFutexAddr != NULL);
- int32_t old = android_atomic_dec(coldFutexAddr);
+ ALOG_ASSERT(coldFutexAddr != nullptr);
+ const int32_t old = android_atomic_dec(coldFutexAddr);
if (old <= 0) {
- syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
+ syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, nullptr);
}
- int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
+ const int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
ALOGE("did not receive expected priority boost on time");
}
@@ -224,7 +184,7 @@
if (rc == 0) {
if (mOldTsValid) {
time_t sec = newTs.tv_sec - mOldTs.tv_sec;
- long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
+ auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0),
"clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld",
mOldTs.tv_sec, mOldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
@@ -267,7 +227,7 @@
mSleepNs = -1;
if (mIsWarm) {
if (sec > 0 || nsec > mUnderrunNs) {
- ATRACE_NAME("underrun");
+ ATRACE_NAME("underrun"); // NOLINT(misc-const-correctness)
// FIXME only log occasionally
ALOGV("underrun: time since last cycle %d.%03ld sec",
(int) sec, nsec / 1000000L);
@@ -298,7 +258,7 @@
#ifdef FAST_THREAD_STATISTICS
if (mIsWarm) {
// advance the FIFO queue bounds
- size_t i = mBounds & (mDumpState->mSamplingN - 1);
+ const size_t i = mBounds & (mDumpState->mSamplingN - 1);
mBounds = (mBounds & 0xFFFF0000) | ((mBounds + 1) & 0xFFFF);
if (mFull) {
//mBounds += 0x10000;
diff --git a/services/audioflinger/fastpath/FastThread.h b/services/audioflinger/fastpath/FastThread.h
new file mode 100644
index 0000000..1f46b29
--- /dev/null
+++ b/services/audioflinger/fastpath/FastThread.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Configuration.h"
+#ifdef CPU_FREQUENCY_STATISTICS
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+#include <utils/Thread.h>
+#include "FastThreadState.h"
+
+namespace android {
+
+// FastThread is the common abstract base class of FastMixer and FastCapture
+class FastThread : public Thread {
+
+public:
+ FastThread(const char *cycleMs, const char *loadUs);
+
+private:
+ // implement Thread::threadLoop()
+ bool threadLoop() override;
+
+protected:
+ // callouts to subclass in same lexical order as they were in original FastMixer.cpp
+ // FIXME need comments
+ virtual const FastThreadState *poll() = 0;
+ virtual void setNBLogWriter(NBLog::Writer *logWriter __unused) { }
+ virtual void onIdle() = 0;
+ virtual void onExit() = 0;
+ virtual bool isSubClassCommand(FastThreadState::Command command) = 0;
+ virtual void onStateChange() = 0;
+ virtual void onWork() = 0;
+
+ // FIXME these former local variables need comments
+ const FastThreadState* mPrevious = nullptr;
+ const FastThreadState* mCurrent = nullptr;
+ struct timespec mOldTs{};
+ bool mOldTsValid = false;
+ int64_t mSleepNs = -1; // -1: busy wait, 0: sched_yield, > 0: nanosleep
+ int64_t mPeriodNs = 0; // expected period; the time required to
+ // render one mix buffer
+ int64_t mUnderrunNs = 0; // underrun likely when write cycle
+ // is greater than this value
+ int64_t mOverrunNs = 0; // overrun likely when write cycle is less than this value
+ int64_t mForceNs = 0; // if overrun detected,
+ // force the write cycle to take this much time
+ int64_t mWarmupNsMin = 0; // warmup complete when write cycle is greater
+ // than or equal to this value
+ int64_t mWarmupNsMax = INT64_MAX; // and less than or equal to this value
+ FastThreadDumpState* mDummyDumpState = nullptr;
+ FastThreadDumpState* mDumpState = nullptr;
+ bool mIgnoreNextOverrun = true; // used to ignore initial overrun
+ // and first after an underrun
+#ifdef FAST_THREAD_STATISTICS
+ struct timespec mOldLoad; // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
+ bool mOldLoadValid = false; // whether oldLoad is valid
+ uint32_t mBounds = 0;
+ bool mFull = false; // whether we have collected at least mSamplingN samples
+#ifdef CPU_FREQUENCY_STATISTICS
+ ThreadCpuUsage mTcu; // for reading the current CPU clock frequency in kHz
+#endif
+#endif
+ unsigned mColdGen = 0; // last observed mColdGen
+ bool mIsWarm = false; // true means ready to mix,
+ // false means wait for warmup before mixing
+ struct timespec mMeasuredWarmupTs{}; // how long did it take for warmup to complete
+ uint32_t mWarmupCycles = 0; // counter of number of loop cycles during warmup phase
+ uint32_t mWarmupConsecutiveInRangeCycles = 0; // number of consecutive cycles in range
+ const sp<NBLog::Writer> mDummyNBLogWriter{new NBLog::Writer()};
+ status_t mTimestampStatus = INVALID_OPERATION;
+
+ FastThreadState::Command mCommand = FastThreadState::INITIAL;
+ bool mAttemptedWrite = false;
+
+ // init in constructor
+ char mCycleMs[16]; // cycle_ms + suffix
+ char mLoadUs[16]; // load_us + suffix
+
+}; // class FastThread
+
+} // namespace android
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/fastpath/FastThreadDumpState.cpp
similarity index 78%
rename from services/audioflinger/FastThreadDumpState.cpp
rename to services/audioflinger/fastpath/FastThreadDumpState.cpp
index e91073f..747cb9e 100644
--- a/services/audioflinger/FastThreadDumpState.cpp
+++ b/services/audioflinger/fastpath/FastThreadDumpState.cpp
@@ -19,32 +19,20 @@
namespace android {
-FastThreadDumpState::FastThreadDumpState() :
- mCommand(FastThreadState::INITIAL), mUnderruns(0), mOverruns(0),
- /* mMeasuredWarmupTs({0, 0}), */
- mWarmupCycles(0)
-#ifdef FAST_THREAD_STATISTICS
- , mSamplingN(0), mBounds(0)
-#endif
+FastThreadDumpState::FastThreadDumpState()
{
- mMeasuredWarmupTs.tv_sec = 0;
- mMeasuredWarmupTs.tv_nsec = 0;
#ifdef FAST_THREAD_STATISTICS
increaseSamplingN(1);
#endif
}
-FastThreadDumpState::~FastThreadDumpState()
-{
-}
-
#ifdef FAST_THREAD_STATISTICS
void FastThreadDumpState::increaseSamplingN(uint32_t samplingN)
{
if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
return;
}
- uint32_t additional = samplingN - mSamplingN;
+ const uint32_t additional = samplingN - mSamplingN;
// sample arrays aren't accessed atomically with respect to the bounds,
// so clearing reduces chance for dumpsys to read random uninitialized samples
memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/fastpath/FastThreadDumpState.h
similarity index 83%
rename from services/audioflinger/FastThreadDumpState.h
rename to services/audioflinger/fastpath/FastThreadDumpState.h
index 0b20e55..b7bc404 100644
--- a/services/audioflinger/FastThreadDumpState.h
+++ b/services/audioflinger/fastpath/FastThreadDumpState.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+#pragma once
+
+#include <type_traits>
#include "Configuration.h"
#include "FastThreadState.h"
@@ -30,13 +31,12 @@
// It has a different lifetime than the FastThread, and so it can't be a member of FastThread.
struct FastThreadDumpState {
FastThreadDumpState();
- /*virtual*/ ~FastThreadDumpState();
- FastThreadState::Command mCommand; // current command
- uint32_t mUnderruns; // total number of underruns
- uint32_t mOverruns; // total number of overruns
- struct timespec mMeasuredWarmupTs; // measured warmup time
- uint32_t mWarmupCycles; // number of loop cycles required to warmup
+ FastThreadState::Command mCommand = FastThreadState::INITIAL; // current command
+ uint32_t mUnderruns = 0; // total number of underruns
+ uint32_t mOverruns = 0; // total number of overruns
+ struct timespec mMeasuredWarmupTs{}; // measured warmup time
+ uint32_t mWarmupCycles = 0; // number of loop cycles required to warmup
#ifdef FAST_THREAD_STATISTICS
// Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
@@ -48,12 +48,12 @@
// This value was chosen such that each array uses 1 small page (4 Kbytes).
static const uint32_t kSamplingNforLowRamDevice = 0x400;
// Corresponding runtime maximum size of sample arrays, must be a power of 2 <= kSamplingN.
- uint32_t mSamplingN;
+ uint32_t mSamplingN = 0;
// The bounds define the interval of valid samples, and are represented as follows:
// newest open (excluded) endpoint = lower 16 bits of bounds, modulo N
// oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
// Number of valid samples is newest - oldest.
- uint32_t mBounds; // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
+ uint32_t mBounds = 0; // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
// The elements in the *Ns arrays are in units of nanoseconds <= 3999999999.
uint32_t mMonotonicNs[kSamplingN]; // delta monotonic (wall clock) time
uint32_t mLoadNs[kSamplingN]; // delta CPU load in time
@@ -67,6 +67,7 @@
}; // struct FastThreadDumpState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadDumpState>);
-#endif // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+} // namespace android
diff --git a/services/audioflinger/FastThreadState.cpp b/services/audioflinger/fastpath/FastThreadState.cpp
similarity index 84%
rename from services/audioflinger/FastThreadState.cpp
rename to services/audioflinger/fastpath/FastThreadState.cpp
index ad5f31f..dfe8e65 100644
--- a/services/audioflinger/FastThreadState.cpp
+++ b/services/audioflinger/fastpath/FastThreadState.cpp
@@ -19,16 +19,6 @@
namespace android {
-FastThreadState::FastThreadState() :
- mCommand(INITIAL), mColdFutexAddr(NULL), mColdGen(0), mDumpState(NULL), mNBLogWriter(NULL)
-
-{
-}
-
-FastThreadState::~FastThreadState()
-{
-}
-
// static
const char *FastThreadState::commandToString(FastThreadState::Command command)
{
@@ -38,7 +28,7 @@
case FastThreadState::COLD_IDLE: return "COLD_IDLE";
case FastThreadState::EXIT: return "EXIT";
}
- return NULL;
+ return nullptr;
}
} // namespace android
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/fastpath/FastThreadState.h
similarity index 69%
rename from services/audioflinger/FastThreadState.h
rename to services/audioflinger/fastpath/FastThreadState.h
index 9fb4e06..8e5bedd 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/fastpath/FastThreadState.h
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_FAST_THREAD_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_STATE_H
+#pragma once
+#include <type_traits>
#include "Configuration.h"
#include <stdint.h>
#include <media/nblog/NBLog.h>
@@ -27,10 +27,7 @@
// Represents a single state of a FastThread
struct FastThreadState {
- FastThreadState();
- /*virtual*/ ~FastThreadState();
-
- typedef uint32_t Command;
+ using Command = uint32_t;
static const Command
INITIAL = 0, // used only for the initial state
HOT_IDLE = 1, // do nothing
@@ -38,18 +35,20 @@
IDLE = 3, // either HOT_IDLE or COLD_IDLE
EXIT = 4; // exit from thread
// additional values defined per subclass
- Command mCommand; // current command
- int32_t* mColdFutexAddr; // for COLD_IDLE only, pointer to the associated futex
- unsigned mColdGen; // increment when COLD_IDLE is requested so it's only performed once
+ Command mCommand = INITIAL; // current command
+ int32_t* mColdFutexAddr = nullptr; // for COLD_IDLE only, pointer to the associated futex
+ unsigned mColdGen = 0; // increment when COLD_IDLE is requested
+ // so it's only performed once
// This might be a one-time configuration rather than per-state
- FastThreadDumpState* mDumpState; // if non-NULL, then update dump state periodically
- NBLog::Writer* mNBLogWriter; // non-blocking logger
+ FastThreadDumpState* mDumpState = nullptr; // if non-NULL, then update dump state periodically
+ NBLog::Writer* mNBLogWriter = nullptr; // non-blocking logger
// returns NULL if command belongs to a subclass
static const char *commandToString(Command command);
}; // struct FastThreadState
-} // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadState>);
-#endif // ANDROID_AUDIO_FAST_THREAD_STATE_H
+} // namespace android
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/fastpath/StateQueue.cpp
similarity index 82%
rename from services/audioflinger/StateQueue.cpp
rename to services/audioflinger/fastpath/StateQueue.cpp
index 38ce2c2..e896d29 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/fastpath/StateQueue.cpp
@@ -38,23 +38,6 @@
}
#endif
-// Constructor and destructor
-
-template<typename T> StateQueue<T>::StateQueue() :
- mAck(NULL), mCurrent(NULL),
- mMutating(&mStates[0]), mExpecting(NULL),
- mInMutation(false), mIsDirty(false), mIsInitialized(false)
-#ifdef STATE_QUEUE_DUMP
- , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump)
-#endif
-{
- atomic_init(&mNext, static_cast<uintptr_t>(0));
-}
-
-template<typename T> StateQueue<T>::~StateQueue()
-{
-}
-
// Observer APIs
template<typename T> const T* StateQueue<T>::poll()
@@ -112,7 +95,7 @@
#endif
// wait for prior push to be acknowledged
- if (mExpecting != NULL) {
+ if (mExpecting != nullptr) {
#ifdef STATE_QUEUE_DUMP
unsigned count = 0;
#endif
@@ -120,7 +103,7 @@
const T *ack = (const T *) mAck; // no additional barrier needed
if (ack == mExpecting) {
// unnecessary as we're about to rewrite
- //mExpecting = NULL;
+ //mExpecting = nullptr;
break;
}
if (block == BLOCK_NEVER) {
@@ -132,7 +115,7 @@
}
++count;
#endif
- nanosleep(&req, NULL);
+ nanosleep(&req, nullptr);
}
#ifdef STATE_QUEUE_DUMP
if (count > 1) {
@@ -156,14 +139,14 @@
// optionally wait for this push or a prior push to be acknowledged
if (block == BLOCK_UNTIL_ACKED) {
- if (mExpecting != NULL) {
+ if (mExpecting != nullptr) {
#ifdef STATE_QUEUE_DUMP
unsigned count = 0;
#endif
for (;;) {
const T *ack = (const T *) mAck; // no additional barrier needed
if (ack == mExpecting) {
- mExpecting = NULL;
+ mExpecting = nullptr;
break;
}
#ifdef STATE_QUEUE_DUMP
@@ -172,7 +155,7 @@
}
++count;
#endif
- nanosleep(&req, NULL);
+ nanosleep(&req, nullptr);
}
#ifdef STATE_QUEUE_DUMP
if (count > 1) {
@@ -187,9 +170,14 @@
} // namespace android
-// Hack to avoid explicit template instantiation of
-// template class StateQueue<FastCaptureState>;
-// template class StateQueue<FastMixerState>;
-#ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS // NOLINT(bugprone-suspicious-include)
-#endif
+// Instantiate StateQueue template for the types we need.
+// This needs to be done in the same translation unit as the template
+// method definitions above.
+
+#include "FastCaptureState.h"
+#include "FastMixerState.h"
+
+namespace android {
+template class StateQueue<FastCaptureState>;
+template class StateQueue<FastMixerState>;
+} // namespace android
diff --git a/services/audioflinger/StateQueue.h b/services/audioflinger/fastpath/StateQueue.h
similarity index 91%
rename from services/audioflinger/StateQueue.h
rename to services/audioflinger/fastpath/StateQueue.h
index 27f6a28..36d986b 100644
--- a/services/audioflinger/StateQueue.h
+++ b/services/audioflinger/fastpath/StateQueue.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_STATE_QUEUE_H
-#define ANDROID_AUDIO_STATE_QUEUE_H
+#pragma once
#include <stdatomic.h>
@@ -124,12 +123,10 @@
#endif
// manages a FIFO queue of states
-template<typename T> class StateQueue {
+// marking as final to avoid derived classes as there are no virtuals.
+template<typename T> class StateQueue final {
public:
- StateQueue();
- virtual ~StateQueue();
-
// Observer APIs
// Poll for a state change. Returns a pointer to a read-only state,
@@ -188,28 +185,29 @@
T mStates[kN]; // written by mutator, read by observer
// "volatile" is meaningless with SMP, but here it indicates that we're using atomic ops
- atomic_uintptr_t mNext; // written by mutator to advance next, read by observer
- volatile const T* mAck; // written by observer to acknowledge advance of next, read by mutator
+ atomic_uintptr_t mNext{}; // written by mutator to advance next, read by observer
+ volatile const T* mAck = nullptr; // written by observer to acknowledge advance of next,
+ // read by mutator
// only used by observer
- const T* mCurrent; // most recent value returned by poll()
+ const T* mCurrent = nullptr; // most recent value returned by poll()
// only used by mutator
- T* mMutating; // where updates by mutator are done in place
- const T* mExpecting; // what the mutator expects mAck to be set to
- bool mInMutation; // whether we're currently in the middle of a mutation
- bool mIsDirty; // whether mutating state has been modified since last push
- bool mIsInitialized; // whether mutating state has been initialized yet
+ T* mMutating{&mStates[0]}; // where updates by mutator are done in place
+ const T* mExpecting = nullptr; // what the mutator expects mAck to be set to
+ bool mInMutation = false; // whether we're currently in the middle of a mutation
+ bool mIsDirty = false; // whether mutating state has been modified since last push
+ bool mIsInitialized = false; // whether mutating state has been initialized yet
#ifdef STATE_QUEUE_DUMP
StateQueueObserverDump mObserverDummyDump; // default area for observer dump if not set
- StateQueueObserverDump* mObserverDump; // pointer to active observer dump, always non-NULL
+ // pointer to active observer dump, always non-nullptr
+ StateQueueObserverDump* mObserverDump{&mObserverDummyDump};
StateQueueMutatorDump mMutatorDummyDump; // default area for mutator dump if not set
- StateQueueMutatorDump* mMutatorDump; // pointer to active mutator dump, always non-NULL
+ // pointer to active mutator dump, always non-nullptr
+ StateQueueMutatorDump* mMutatorDump{&mMutatorDummyDump};
#endif
}; // class StateQueue
} // namespace android
-
-#endif // ANDROID_AUDIO_STATE_QUEUE_H
diff --git a/services/audioflinger/sounddose/Android.bp b/services/audioflinger/sounddose/Android.bp
index 0a8c8be..2cab5d1 100644
--- a/services/audioflinger/sounddose/Android.bp
+++ b/services/audioflinger/sounddose/Android.bp
@@ -7,12 +7,39 @@
default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
}
+audioflinger_sounddose_tidy_errors = audioflinger_base_tidy_errors + [
+ "modernize-avoid-c-arrays",
+ "modernize-deprecated-headers",
+ "modernize-pass-by-value",
+ "modernize-use-auto",
+ "modernize-use-nodiscard",
+
+ // TODO(b/275642749) Reenable these warnings
+ "-misc-non-private-member-variables-in-classes",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_sounddose_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: audioflinger_base_cflags,
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: audioflinger_sounddose_tidy_errors,
+ tidy_checks_as_errors: audioflinger_sounddose_tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
cc_library {
name: "libsounddose",
double_loadable: true,
defaults: [
+ "audioflinger_sounddose_flags_defaults",
"latest_android_media_audio_common_types_ndk_shared",
"latest_android_hardware_audio_core_sounddose_ndk_shared",
"latest_android_hardware_audio_sounddose_ndk_shared",
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index a114a38..21f346e 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -30,7 +30,6 @@
namespace android {
using aidl::android::media::audio::common::AudioDevice;
-using aidl::android::media::audio::common::AudioDeviceAddress;
namespace {
@@ -48,7 +47,7 @@
sp<audio_utils::MelProcessor> SoundDoseManager::getOrCreateProcessorForDevice(
audio_port_handle_t deviceId, audio_io_handle_t streamHandle, uint32_t sampleRate,
size_t channelCount, audio_format_t format) {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (mHalSoundDose != nullptr && mEnabledCsd) {
ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
@@ -86,8 +85,9 @@
bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
ALOGV("%s", __func__);
+ std::shared_ptr<HalSoundDoseCallback> halSoundDoseCallback;
{
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
mHalSoundDose = halSoundDose;
if (halSoundDose == nullptr) {
@@ -106,9 +106,11 @@
mHalSoundDoseCallback =
ndk::SharedRefBase::make<HalSoundDoseCallback>(this);
}
+ halSoundDoseCallback = mHalSoundDoseCallback;
}
- auto status = halSoundDose->registerSoundDoseCallback(mHalSoundDoseCallback);
+ auto status = halSoundDose->registerSoundDoseCallback(halSoundDoseCallback);
+
if (!status.isOk()) {
// Not a warning since this can happen if the callback was registered before
ALOGI("%s: Cannot register HAL sound dose callback with status message: %s",
@@ -121,7 +123,7 @@
void SoundDoseManager::setOutputRs2UpperBound(float rs2Value) {
ALOGV("%s", __func__);
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (mHalSoundDose != nullptr) {
// using the HAL sound dose interface
@@ -134,9 +136,9 @@
}
for (auto& streamProcessor : mActiveProcessors) {
- sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
+ const sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
if (processor != nullptr) {
- status_t result = processor->setOutputRs2UpperBound(rs2Value);
+ const status_t result = processor->setOutputRs2UpperBound(rs2Value);
if (result != NO_ERROR) {
ALOGW("%s: could not set RS2 upper bound %f for stream %d", __func__, rs2Value,
streamProcessor.first);
@@ -148,7 +150,7 @@
}
void SoundDoseManager::removeStreamProcessor(audio_io_handle_t streamHandle) {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
auto callbackToRemove = mActiveProcessors.find(streamHandle);
if (callbackToRemove != mActiveProcessors.end()) {
mActiveProcessors.erase(callbackToRemove);
@@ -156,7 +158,7 @@
}
audio_port_handle_t SoundDoseManager::getIdForAudioDevice(const AudioDevice& audioDevice) const {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
audio_devices_t type;
std::string address;
@@ -178,14 +180,14 @@
void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
const audio_port_handle_t deviceId) {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
ALOGI("%s: map address: %d to device id: %d", __func__, adt.mType, deviceId);
mActiveDevices[adt] = deviceId;
mActiveDeviceTypes[deviceId] = adt.mType;
}
void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
for (auto activeDevice = mActiveDevices.begin(); activeDevice != mActiveDevices.end();) {
if (activeDevice->second == deviceId) {
ALOGI("%s: clear mapping type: %d to deviceId: %d",
@@ -303,7 +305,7 @@
ALOGV("%s", __func__);
auto soundDoseManager = mSoundDoseManager.promote();
if (soundDoseManager != nullptr) {
- std::lock_guard _l(soundDoseManager->mLock);
+ const std::lock_guard _l(soundDoseManager->mLock);
*value = soundDoseManager->mRs2UpperBound;
}
return binder::Status::ok();
@@ -348,7 +350,7 @@
}
void SoundDoseManager::updateAttenuation(float attenuationDB, audio_devices_t deviceType) {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
ALOGV("%s: updating MEL processor attenuation for device type %d to %f",
__func__, deviceType, attenuationDB);
mMelAttenuationDB[deviceType] = attenuationDB;
@@ -368,7 +370,7 @@
void SoundDoseManager::setCsdEnabled(bool enabled) {
ALOGV("%s", __func__);
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
mEnabledCsd = enabled;
for (auto& activeEntry : mActiveProcessors) {
@@ -384,7 +386,7 @@
}
bool SoundDoseManager::isCsdEnabled() {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
return mEnabledCsd;
}
@@ -392,52 +394,51 @@
// invalidate any HAL sound dose interface used
setHalSoundDoseInterface(nullptr);
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
mUseFrameworkMel = useFrameworkMel;
}
bool SoundDoseManager::forceUseFrameworkMel() const {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
return mUseFrameworkMel;
}
void SoundDoseManager::setComputeCsdOnAllDevices(bool computeCsdOnAllDevices) {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
mComputeCsdOnAllDevices = computeCsdOnAllDevices;
}
bool SoundDoseManager::forceComputeCsdOnAllDevices() const {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
return mComputeCsdOnAllDevices;
}
bool SoundDoseManager::isSoundDoseHalSupported() const {
- if (!mEnabledCsd) {
- return false;
+ {
+ const std::lock_guard _l(mLock);
+ if (!mEnabledCsd) return false;
}
std::shared_ptr<ISoundDose> halSoundDose;
getHalSoundDose(&halSoundDose);
- if (mHalSoundDose == nullptr) {
- return false;
- }
- return true;
+ return halSoundDose != nullptr;
}
void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
*halSoundDose = mHalSoundDose;
}
void SoundDoseManager::resetSoundDose() {
- std::lock_guard lock(mLock);
+ const std::lock_guard lock(mLock);
mSoundDose = nullptr;
}
void SoundDoseManager::resetCsd(float currentCsd,
const std::vector<media::SoundDoseRecord>& records) {
- std::lock_guard lock(mLock);
+ const std::lock_guard lock(mLock);
std::vector<audio_utils::CsdRecord> resetRecords;
+ resetRecords.reserve(records.size());
for (const auto& record : records) {
resetRecords.emplace_back(record.timestamp, record.duration, record.value,
record.averageMel);
@@ -455,13 +456,13 @@
std::vector<audio_utils::CsdRecord> records;
float currentCsd;
{
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (!mEnabledCsd) {
return;
}
- int64_t timestampSec = getMonotonicSecond();
+ const int64_t timestampSec = getMonotonicSecond();
// only for internal callbacks
records = mMelAggregator->aggregateAndAddNewMelRecord(audio_utils::MelRecord(
@@ -475,6 +476,7 @@
if (records.size() > 0 && soundDoseCallback != nullptr) {
std::vector<media::SoundDoseRecord> newRecordsToReport;
+ newRecordsToReport.resize(records.size());
for (const auto& record : records) {
newRecordsToReport.emplace_back(csdRecordToSoundDoseRecord(record));
}
@@ -484,7 +486,7 @@
}
sp<media::ISoundDoseCallback> SoundDoseManager::getSoundDoseCallback() const {
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (mSoundDose == nullptr) {
return nullptr;
}
@@ -496,7 +498,7 @@
ALOGV("%s: Momentary exposure for device %d triggered: %f MEL", __func__, deviceId, currentMel);
{
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (!mEnabledCsd) {
return;
}
@@ -512,7 +514,7 @@
const sp<media::ISoundDoseCallback>& callback) {
ALOGV("%s: Register ISoundDoseCallback", __func__);
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (mSoundDose == nullptr) {
mSoundDose = sp<SoundDose>::make(this, callback);
}
@@ -522,7 +524,7 @@
std::string SoundDoseManager::dump() const {
std::string output;
{
- std::lock_guard _l(mLock);
+ const std::lock_guard _l(mLock);
if (!mEnabledCsd) {
base::StringAppendF(&output, "CSD is disabled");
return output;
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index 6c02afb..9ed0661 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -129,7 +129,7 @@
mSoundDoseCallback(callback) {}
/** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */
- virtual void binderDied(const wp<IBinder>& who);
+ void binderDied(const wp<IBinder>& who) override;
/** BnSoundDose override */
binder::Status setOutputRs2UpperBound(float value) override;
diff --git a/services/audioflinger/timing/Android.bp b/services/audioflinger/timing/Android.bp
index 17ce8bd..30ebca0 100644
--- a/services/audioflinger/timing/Android.bp
+++ b/services/audioflinger/timing/Android.bp
@@ -7,9 +7,39 @@
default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
}
+audioflinger_timing_tidy_errors = audioflinger_base_tidy_errors + [
+ "modernize-avoid-c-arrays",
+ "modernize-deprecated-headers",
+ "modernize-pass-by-value",
+ "modernize-use-auto",
+ "modernize-use-nodiscard",
+
+ // TODO(b/275642749) Reenable these warnings
+ "-misc-non-private-member-variables-in-classes",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_timing_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: audioflinger_base_cflags,
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: audioflinger_timing_tidy_errors,
+ tidy_checks_as_errors: audioflinger_timing_tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
cc_library {
name: "libaudioflinger_timing",
+ defaults: [
+ "audioflinger_timing_flags_defaults",
+ ],
+
host_supported: true,
srcs: [
diff --git a/services/audioflinger/timing/MonotonicFrameCounter.h b/services/audioflinger/timing/MonotonicFrameCounter.h
index 0ea9510..8468130 100644
--- a/services/audioflinger/timing/MonotonicFrameCounter.h
+++ b/services/audioflinger/timing/MonotonicFrameCounter.h
@@ -58,19 +58,19 @@
* This offset is sufficient to ensure monotonicity after flush is called,
* suitability for any other purpose is *not* guaranteed.
*/
- int64_t getOffsetFrameCount() const { return mOffsetFrameCount; }
+ [[nodiscard]] int64_t getOffsetFrameCount() const { return mOffsetFrameCount; }
/**
* Returns the last received frameCount.
*/
- int64_t getLastReceivedFrameCount() const {
+ [[nodiscard]] int64_t getLastReceivedFrameCount() const {
return mLastReceivedFrameCount;
}
/**
* Returns the last reported frameCount from updateAndGetMonotonicFrameCount().
*/
- int64_t getLastReportedFrameCount() const {
+ [[nodiscard]] int64_t getLastReportedFrameCount() const {
// This is consistent after onFlush().
return mOffsetFrameCount + mLastReceivedFrameCount;
}
diff --git a/services/audioflinger/timing/SyncEvent.h b/services/audioflinger/timing/SyncEvent.h
new file mode 100644
index 0000000..b5a3b40
--- /dev/null
+++ b/services/audioflinger/timing/SyncEvent.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+
+#include <media/AudioSystem.h>
+#include <utils/RefBase.h>
+
+namespace android::audioflinger {
+
+class SyncEvent;
+using SyncEventCallback = std::function<void(const wp<SyncEvent>& event)>;
+
+class SyncEvent : public RefBase {
+public:
+ SyncEvent(AudioSystem::sync_event_t type,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
+ const SyncEventCallback& callBack,
+ const wp<RefBase>& cookie)
+ : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
+ mCookie(cookie), mCallback(callBack)
+ {}
+
+ void trigger() {
+ std::lock_guard l(mLock);
+ if (mCallback) mCallback(wp<SyncEvent>::fromExisting(this));
+ }
+
+ bool isCancelled() const {
+ std::lock_guard l(mLock);
+ return mCallback == nullptr;
+ }
+
+ void cancel() {
+ std::lock_guard l(mLock);
+ mCallback = nullptr;
+ }
+
+ AudioSystem::sync_event_t type() const { return mType; }
+ audio_session_t triggerSession() const { return mTriggerSession; }
+ audio_session_t listenerSession() const { return mListenerSession; }
+ const wp<RefBase>& cookie() const { return mCookie; }
+
+private:
+ const AudioSystem::sync_event_t mType;
+ const audio_session_t mTriggerSession;
+ const audio_session_t mListenerSession;
+ const wp<RefBase> mCookie;
+ mutable std::mutex mLock;
+ SyncEventCallback mCallback GUARDED_BY(mLock);
+};
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/SynchronizedRecordState.h b/services/audioflinger/timing/SynchronizedRecordState.h
new file mode 100644
index 0000000..f40d41b
--- /dev/null
+++ b/services/audioflinger/timing/SynchronizedRecordState.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "SyncEvent.h"
+
+#pragma push_macro("LOG_TAG")
+#undef LOG_TAG
+#define LOG_TAG "SynchronizedRecordState"
+
+namespace android::audioflinger {
+
+class SynchronizedRecordState {
+public:
+ explicit SynchronizedRecordState(uint32_t sampleRate)
+ : mSampleRate(sampleRate)
+ {}
+
+ void clear() {
+ std::lock_guard lg(mLock);
+ clear_l();
+ }
+
+ // Called by the RecordThread when recording is starting.
+ void startRecording(const sp<SyncEvent>& event) {
+ std::lock_guard lg(mLock);
+ mSyncStartEvent = event;
+ // Sync event can be cancelled by the trigger session if the track is not in a
+ // compatible state in which case we start record immediately
+ if (mSyncStartEvent->isCancelled()) {
+ clear_l();
+ } else {
+ mFramesToDrop = -(ssize_t)
+ ((AudioSystem::kSyncRecordStartTimeOutMs * mSampleRate) / 1000);
+ }
+ }
+
+ // Invoked by SyncEvent callback.
+ void onPlaybackFinished(const sp<SyncEvent>& event, size_t framesToDrop = 1) {
+ std::lock_guard lg(mLock);
+ if (event == mSyncStartEvent) {
+ mFramesToDrop = framesToDrop; // compute this
+ ALOGV("%s: framesToDrop:%zd", __func__, mFramesToDrop);
+ }
+ }
+
+ // Returns the current FramesToDrop counter
+ //
+ // if <0 waiting (drop the frames)
+ // if >0 draining (drop the frames)
+ // else if ==0 proceed to record.
+ ssize_t updateRecordFrames(size_t frames) {
+ std::lock_guard lg(mLock);
+ if (mFramesToDrop > 0) {
+ // we've been triggered, we count down for start delay
+ ALOGV("%s: trigger countdown %zd by %zu frames", __func__, mFramesToDrop, frames);
+ mFramesToDrop -= (ssize_t)frames;
+ if (mFramesToDrop <= 0) clear_l();
+ } else if (mFramesToDrop < 0) {
+ // we're waiting to be triggered.
+ // ALOGD("%s: timeout countup %zd with %zu frames", __func__, mFramesToDrop, frames);
+ mFramesToDrop += (ssize_t)frames;
+ if (mFramesToDrop >= 0 || !mSyncStartEvent || mSyncStartEvent->isCancelled()) {
+ ALOGW("Synced record %s, trigger session %d",
+ (mFramesToDrop >= 0) ? "timed out" : "cancelled",
+ (mSyncStartEvent) ? mSyncStartEvent->triggerSession()
+ : AUDIO_SESSION_NONE);
+ clear_l();
+ }
+ }
+ return mFramesToDrop;
+ }
+
+private:
+ const uint32_t mSampleRate;
+
+ std::mutex mLock;
+ // number of captured frames to drop after the start sync event has been received.
+ // when < 0, maximum frames to drop before starting capture even if sync event is
+ // not received
+ ssize_t mFramesToDrop GUARDED_BY(mLock) = 0;
+
+ // sync event triggering actual audio capture. Frames read before this event will
+ // be dropped and therefore not read by the application.
+ sp<SyncEvent> mSyncStartEvent GUARDED_BY(mLock);
+
+ void clear_l() REQUIRES(mLock) {
+ if (mSyncStartEvent) {
+ mSyncStartEvent->cancel();
+ mSyncStartEvent.clear();
+ }
+ mFramesToDrop = 0;
+ }
+};
+
+} // namespace android::audioflinger
+
+#pragma pop_macro("LOG_TAG")
diff --git a/services/audioflinger/timing/tests/Android.bp b/services/audioflinger/timing/tests/Android.bp
index 29267a6..d1e5563 100644
--- a/services/audioflinger/timing/tests/Android.bp
+++ b/services/audioflinger/timing/tests/Android.bp
@@ -8,6 +8,31 @@
}
cc_test {
+ name: "mediasyncevent_tests",
+
+ host_supported: true,
+
+ srcs: [
+ "mediasyncevent_tests.cpp"
+ ],
+
+ header_libs: [
+ "libaudioclient_headers",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libutils", // RefBase
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+cc_test {
name: "monotonicframecounter_tests",
host_supported: true,
@@ -26,4 +51,29 @@
"-Werror",
"-Wextra",
],
-}
\ No newline at end of file
+}
+
+cc_test {
+ name: "synchronizedrecordstate_tests",
+
+ host_supported: true,
+
+ srcs: [
+ "synchronizedrecordstate_tests.cpp"
+ ],
+
+ header_libs: [
+ "libaudioclient_headers",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libutils", // RefBase
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ }
\ No newline at end of file
diff --git a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
new file mode 100644
index 0000000..2922d90
--- /dev/null
+++ b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "mediasyncevent_tests"
+
+#include "../SyncEvent.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(MediaSyncEventTests, Basic) {
+ struct Cookie : public RefBase {};
+
+ // These variables are set by trigger().
+ bool triggered = false;
+ wp<SyncEvent> param;
+
+ constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+ constexpr auto triggerSession = audio_session_t(10);
+ constexpr auto listenerSession = audio_session_t(11);
+ const SyncEventCallback callback =
+ [&](const wp<SyncEvent>& event) {
+ triggered = true;
+ param = event;
+ };
+ const auto cookie = sp<Cookie>::make();
+
+ // Since the callback uses a weak pointer to this,
+ // don't allocate on the stack.
+ auto syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+
+ ASSERT_EQ(type, syncEvent->type());
+ ASSERT_EQ(triggerSession, syncEvent->triggerSession());
+ ASSERT_EQ(listenerSession, syncEvent->listenerSession());
+ ASSERT_EQ(cookie, syncEvent->cookie());
+ ASSERT_FALSE(triggered);
+
+ syncEvent->trigger();
+ ASSERT_TRUE(triggered);
+ ASSERT_EQ(param, syncEvent);
+
+ ASSERT_FALSE(syncEvent->isCancelled());
+ syncEvent->cancel();
+ ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+} // namespace
diff --git a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
new file mode 100644
index 0000000..ee5d269
--- /dev/null
+++ b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "synchronizedrecordstate_tests"
+
+#include "../SynchronizedRecordState.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(SynchronizedRecordStateTests, Basic) {
+ struct Cookie : public RefBase {};
+
+ // These variables are set by trigger().
+ bool triggered = false;
+ wp<SyncEvent> param;
+
+ constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+ constexpr auto triggerSession = audio_session_t(10);
+ constexpr auto listenerSession = audio_session_t(11);
+ const SyncEventCallback callback =
+ [&](const wp<SyncEvent>& event) {
+ triggered = true;
+ param = event;
+ };
+ const auto cookie = sp<Cookie>::make();
+
+ // Check timeout.
+ SynchronizedRecordState recordState(48000 /* sampleRate */);
+ auto syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+ recordState.startRecording(syncEvent);
+ recordState.updateRecordFrames(2);
+ ASSERT_FALSE(triggered);
+ ASSERT_EQ(0, recordState.updateRecordFrames(1'000'000'000));
+ ASSERT_FALSE(triggered);
+ ASSERT_TRUE(syncEvent->isCancelled());
+
+ // Check count down after track is complete.
+ syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+ recordState.startRecording(syncEvent);
+ recordState.onPlaybackFinished(syncEvent, 10);
+ ASSERT_EQ(1, recordState.updateRecordFrames(9));
+ ASSERT_FALSE(triggered);
+ ASSERT_EQ(0, recordState.updateRecordFrames(2));
+ ASSERT_FALSE(triggered);
+ ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+}
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 1d570b7..8b76842 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -7,9 +7,13 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_library_static {
+cc_library {
name: "libaudiopolicycomponents",
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_shared",
+ ],
+
srcs: [
"src/AudioCollections.cpp",
"src/AudioInputDescriptor.cpp",
@@ -31,7 +35,11 @@
"src/TypeConverter.cpp",
],
shared_libs: [
+ "audioclient-types-aidl-cpp",
+ "audiopolicy-types-aidl-cpp",
+ "libaudioclient_aidl_conversion",
"libaudiofoundation",
+ "libaudiopolicy",
"libbase",
"libcutils",
"libhidlbase",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 32c78a1..1f6002f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -23,6 +23,7 @@
#include <DeviceDescriptor.h>
#include <HwModule.h>
+#include <android/media/AudioPolicyConfig.h>
#include <error/Result.h>
#include <utils/StrongPointer.h>
#include <utils/RefBase.h>
@@ -42,6 +43,8 @@
// Surround formats, with an optional list of subformats that are equivalent from users' POV.
using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
+ // The source used to indicate the configuration from the AIDL HAL.
+ static const constexpr char* const kAidlConfigSource = "AIDL HAL";
// The source used to indicate the default fallback configuration.
static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
// The suffix of the "engine default" implementation shared library name.
@@ -49,6 +52,9 @@
// Creates the default (fallback) configuration.
static sp<const AudioPolicyConfig> createDefault();
+ // Attempts to load the configuration from the AIDL config falls back to default on failure.
+ static sp<const AudioPolicyConfig> loadFromApmAidlConfigWithFallback(
+ const media::AudioPolicyConfig& aidl);
// Attempts to load the configuration from the XML file, falls back to default on failure.
// If the XML file path is not provided, uses `audio_get_audio_policy_config_file` function.
static sp<const AudioPolicyConfig> loadFromApmXmlConfigWithFallback(
@@ -140,6 +146,7 @@
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 436fcc1..e994758 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -39,7 +39,8 @@
class HwModule : public RefBase
{
public:
- explicit HwModule(const char *name, uint32_t halVersionMajor = 0, uint32_t halVersionMinor = 0);
+ explicit HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor);
+ HwModule(const char *name, uint32_t halVersion = 0);
~HwModule();
const char *getName() const { return mName.string(); }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 09ca989..4877166 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -701,12 +701,6 @@
}
}
- // 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",
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 42c76e2..e214ae9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -19,6 +19,9 @@
#include <AudioPolicyConfig.h>
#include <IOProfile.h>
#include <Serializer.h>
+#include <hardware/audio.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
#include <media/AudioProfile.h>
#include <system/audio.h>
#include <system/audio_config.h>
@@ -26,6 +29,142 @@
namespace android {
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+
+namespace {
+
+ConversionResult<sp<PolicyAudioPort>>
+aidl2legacy_portId_PolicyAudioPort(int32_t portId,
+ const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+ if (auto it = ports.find(portId); it != ports.end()) {
+ return it->second;
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<sp<AudioRoute>>
+aidl2legacy_AudioRoute(const media::AudioRoute& aidl,
+ const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+ auto legacy = sp<AudioRoute>::make(aidl.isExclusive ? AUDIO_ROUTE_MUX : AUDIO_ROUTE_MIX);
+ auto legacySink = VALUE_OR_RETURN(aidl2legacy_portId_PolicyAudioPort(aidl.sinkPortId, ports));
+ legacy->setSink(legacySink);
+ PolicyAudioPortVector legacySources;
+ for (int32_t portId : aidl.sourcePortIds) {
+ sp<PolicyAudioPort> legacyPort = VALUE_OR_RETURN(
+ aidl2legacy_portId_PolicyAudioPort(portId, ports));
+ legacySources.add(legacyPort);
+ }
+ legacy->setSources(legacySources);
+ legacySink->addRoute(legacy);
+ for (const auto& legacySource : legacySources) {
+ legacySource->addRoute(legacy);
+ }
+ return legacy;
+}
+
+status_t aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule& aidl,
+ sp<HwModule>* legacy,
+ DeviceVector* attachedInputDevices, DeviceVector* attachedOutputDevices,
+ sp<DeviceDescriptor>* defaultOutputDevice) {
+ *legacy = sp<HwModule>::make(aidl.name.c_str(), AUDIO_DEVICE_API_VERSION_CURRENT);
+ audio_module_handle_t legacyHandle = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_int32_t_audio_module_handle_t(aidl.handle));
+ (*legacy)->setHandle(legacyHandle);
+ IOProfileCollection mixPorts;
+ DeviceVector devicePorts;
+ const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+ std::unordered_map<int32_t, sp<PolicyAudioPort>> ports;
+ for (const auto& aidlPort : aidl.ports) {
+ const bool isInput = aidlPort.flags.getTag() == AudioIoFlags::input;
+ audio_port_v7 legacyPort = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioPort_audio_port_v7(aidlPort, isInput));
+ // This conversion fills out both 'hal' and 'sys' parts.
+ media::AudioPortFw fwPort = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_port_v7_AudioPortFw(legacyPort));
+ // Since audio_port_v7 lacks some fields, for example, 'maxOpen/ActiveCount',
+ // replace the converted data with the actual data from the HAL.
+ fwPort.hal = aidlPort;
+ if (aidlPort.ext.getTag() == AudioPortExt::mix) {
+ auto mixPort = sp<IOProfile>::make("", AUDIO_PORT_ROLE_NONE);
+ RETURN_STATUS_IF_ERROR(mixPort->readFromParcelable(fwPort));
+ sortAudioProfiles(mixPort->getAudioProfiles());
+ mixPorts.add(mixPort);
+ ports.emplace(aidlPort.id, mixPort);
+ } else if (aidlPort.ext.getTag() == AudioPortExt::device) {
+ // In the legacy XML, device ports use 'tagName' instead of 'AudioPort.name'.
+ auto devicePort =
+ sp<DeviceDescriptor>::make(AUDIO_DEVICE_NONE, aidlPort.name);
+ RETURN_STATUS_IF_ERROR(devicePort->readFromParcelable(fwPort));
+ devicePort->setName("");
+ auto& profiles = devicePort->getAudioProfiles();
+ if (profiles.empty()) {
+ profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
+ } else {
+ sortAudioProfiles(profiles);
+ }
+ devicePorts.add(devicePort);
+ ports.emplace(aidlPort.id, devicePort);
+
+ if (const auto& deviceExt = aidlPort.ext.get<AudioPortExt::device>();
+ deviceExt.device.type.connection.empty()) { // Attached device
+ if (isInput) {
+ attachedInputDevices->add(devicePort);
+ } else {
+ attachedOutputDevices->add(devicePort);
+ if ((deviceExt.flags & defaultDeviceFlag) != 0) {
+ *defaultOutputDevice = devicePort;
+ }
+ }
+ }
+ } else {
+ return BAD_VALUE;
+ }
+ }
+ (*legacy)->setProfiles(mixPorts);
+ (*legacy)->setDeclaredDevices(devicePorts);
+ AudioRouteVector routes;
+ for (const auto& aidlRoute : aidl.routes) {
+ sp<AudioRoute> legacy = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioRoute(aidlRoute, ports));
+ routes.add(legacy);
+ }
+ (*legacy)->setRoutes(routes);
+ return OK;
+}
+
+status_t aidl2legacy_AudioHwModules_HwModuleCollection(
+ const std::vector<media::AudioHwModule>& aidl,
+ HwModuleCollection* legacyModules, DeviceVector* attachedInputDevices,
+ DeviceVector* attachedOutputDevices, sp<DeviceDescriptor>* defaultOutputDevice) {
+ for (const auto& aidlModule : aidl) {
+ sp<HwModule> legacy;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModule_HwModule(aidlModule, &legacy,
+ attachedInputDevices, attachedOutputDevices, defaultOutputDevice));
+ legacyModules->add(legacy);
+ }
+ return OK;
+}
+
+using SurroundFormatFamily = AudioPolicyConfig::SurroundFormats::value_type;
+ConversionResult<SurroundFormatFamily>
+aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily& aidl) {
+ audio_format_t legacyPrimary = VALUE_OR_RETURN(
+ aidl2legacy_AudioFormatDescription_audio_format_t(aidl.primaryFormat));
+ std::unordered_set<audio_format_t> legacySubs = VALUE_OR_RETURN(
+ convertContainer<std::unordered_set<audio_format_t>>(
+ aidl.subFormats, aidl2legacy_AudioFormatDescription_audio_format_t));
+ return std::make_pair(legacyPrimary, legacySubs);
+}
+
+ConversionResult<AudioPolicyConfig::SurroundFormats>
+aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig& aidl) {
+ return convertContainer<AudioPolicyConfig::SurroundFormats>(aidl.formatFamilies,
+ aidl2legacy_SurroundFormatFamily);
+};
+
+} // namespace
+
// static
sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
auto config = sp<AudioPolicyConfig>::make();
@@ -34,6 +173,16 @@
}
// static
+sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmAidlConfigWithFallback(
+ const media::AudioPolicyConfig& aidl) {
+ auto config = sp<AudioPolicyConfig>::make();
+ if (status_t status = config->loadFromAidl(aidl); status == NO_ERROR) {
+ return config;
+ }
+ return createDefault();
+}
+
+// static
sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
const std::string& xmlFilePath) {
const std::string filePath =
@@ -100,6 +249,18 @@
}
}
+status_t AudioPolicyConfig::loadFromAidl(const media::AudioPolicyConfig& aidl) {
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModules_HwModuleCollection(aidl.modules,
+ &mHwModules, &mInputDevices, &mOutputDevices, &mDefaultOutputDevice));
+ mIsCallScreenModeSupported = std::find(aidl.supportedModes.begin(), aidl.supportedModes.end(),
+ media::audio::common::AudioMode::CALL_SCREEN) != aidl.supportedModes.end();
+ mSurroundFormats = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
+ mSource = kAidlConfigSource;
+ // No need to augmentData() as AIDL HAL must provide correct mic addresses.
+ return NO_ERROR;
+}
+
status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
if (xmlFilePath.empty()) {
ALOGE("Audio policy configuration file name is empty");
@@ -131,7 +292,8 @@
mOutputDevices.add(mDefaultOutputDevice);
mInputDevices.add(defaultInputDevice);
- sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
+ sp<HwModule> module = new HwModule(
+ AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_DEVICE_API_VERSION_2_0);
mHwModules.add(module);
sp<OutputProfile> outProfile = new OutputProfile("primary");
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 418b7eb..5f14ee4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -33,6 +33,13 @@
setHalVersion(halVersionMajor, halVersionMinor);
}
+HwModule::HwModule(const char *name, uint32_t halVersion)
+ : mName(String8(name)),
+ mHandle(AUDIO_MODULE_HANDLE_NONE),
+ mHalVersion(halVersion)
+{
+}
+
HwModule::~HwModule()
{
for (size_t i = 0; i < mOutputProfiles.size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 98d7d59..03ab3f8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -75,7 +75,7 @@
if (checkExactAudioProfile(&config) != NO_ERROR) {
return false;
}
- } else if (checkCompatibleAudioProfile(
+ } else if (checkExactAudioProfile(&config) != NO_ERROR && checkCompatibleAudioProfile(
myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) {
return false;
}
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index 50c5eab..6c46c54 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -51,10 +51,10 @@
"libaudiopolicyengine_common_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_config",
],
shared_libs: [
"libaudiofoundation",
+ "libaudiopolicycomponents",
],
}
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index bac51f5..b9c94a4 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -16,6 +16,9 @@
#pragma once
+#include <functional>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <EngineConfig.h>
#include <EngineInterface.h>
#include <ProductStrategy.h>
@@ -113,6 +116,9 @@
status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
AudioDeviceTypeAddrVector &devices) const override;
+ engineConfig::ParsingResult loadAudioPolicyEngineConfig(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig);
+
engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
@@ -176,6 +182,8 @@
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 7d6a308..218aff8 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -115,10 +115,53 @@
return PRODUCT_STRATEGY_NONE;
}
+engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig)
+{
+ engineConfig::ParsingResult result = engineConfig::convert(aidlConfig);
+ if (result.parsedConfig == nullptr) {
+ ALOGE("%s: There was an error parsing AIDL data", __func__);
+ result = {std::make_unique<engineConfig::Config>(gDefaultEngineConfig), 1};
+ } else {
+ // It is allowed for the HAL to return an empty list of strategies.
+ if (result.parsedConfig->productStrategies.empty()) {
+ result.parsedConfig->productStrategies = gDefaultEngineConfig.productStrategies;
+ }
+ }
+ return processParsingResult(std::move(result));
+}
+
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
{
+ auto fileExists = [](const char* path) {
+ struct stat fileStat;
+ return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
+ };
+ const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
+ engineConfig::ParsingResult result =
+ fileExists(filePath.c_str()) ?
+ engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
+ if (result.parsedConfig == nullptr) {
+ ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
+ engineConfig::Config config = gDefaultEngineConfig;
+ android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
+ result = {std::make_unique<engineConfig::Config>(config),
+ static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
+ } else {
+ // Append for internal use only volume groups (e.g. rerouting/patch)
+ result.parsedConfig->volumeGroups.insert(
+ std::end(result.parsedConfig->volumeGroups),
+ std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
+ }
+ ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+ return processParsingResult(std::move(result));
+}
+
+engineConfig::ParsingResult EngineBase::processParsingResult(
+ engineConfig::ParsingResult&& rawResult)
+{
auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
- // Ensure name unicity to prevent duplicate
+ // Ensure volume group name uniqueness.
LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),
[&volumeConfig](const auto &volumeGroup) {
return volumeConfig.name == volumeGroup.second->getName(); }),
@@ -158,42 +201,21 @@
});
return iter != end(volumeGroups);
};
- auto fileExists = [](const char* path) {
- struct stat fileStat;
- return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
- };
- const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
- auto result = fileExists(filePath.c_str()) ?
- engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
- if (result.parsedConfig == nullptr) {
- ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
- engineConfig::Config config = gDefaultEngineConfig;
- android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
- result = {std::make_unique<engineConfig::Config>(config),
- static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
- } else {
- // Append for internal use only volume groups (e.g. rerouting/patch)
- result.parsedConfig->volumeGroups.insert(
- std::end(result.parsedConfig->volumeGroups),
- std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
- }
+ auto result = std::move(rawResult);
// Append for internal use only strategies (e.g. rerouting/patch)
result.parsedConfig->productStrategies.insert(
std::end(result.parsedConfig->productStrategies),
std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
-
- ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
-
engineConfig::VolumeGroup defaultVolumeConfig;
engineConfig::VolumeGroup defaultSystemVolumeConfig;
for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
// save default volume config for streams not defined in configuration
- if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
+ if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_MUSIC)) == 0) {
defaultVolumeConfig = volumeConfig;
}
- if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
+ if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_PATCH)) == 0) {
defaultSystemVolumeConfig = volumeConfig;
}
loadVolumeConfig(mVolumeGroups, volumeConfig);
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 1d3ad1c..0d25955 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -155,7 +155,7 @@
return iter.second->getId();
}
if (score > matchScore) {
- bestStrategyOrdefault = iter.second->getId();;
+ bestStrategyOrdefault = iter.second->getId();
matchScore = score;
}
}
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index 459cc78..12597de 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -22,11 +22,13 @@
"-Wextra",
],
shared_libs: [
- "libmedia_helper",
- "libxml2",
- "libutils",
- "liblog",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudiopolicycomponents",
"libcutils",
+ "liblog",
+ "libmedia_helper",
+ "libutils",
+ "libxml2",
],
header_libs: [
"libaudio_system_headers",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 4de16c5..119dbd6 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -16,10 +16,11 @@
#pragma once
-#include <system/audio.h>
-
#include <string>
#include <vector>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio.h>
#include <utils/Errors.h>
struct _xmlNode;
@@ -116,6 +117,7 @@
*/
ParsingResult parse(const char* path = DEFAULT_PATH);
android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups);
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
// Exposed for testing.
android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups);
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index ac117f0..ca78ce7 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -14,26 +14,30 @@
* limitations under the License.
*/
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
#define LOG_TAG "APM::AudioPolicyEngine/Config"
//#define LOG_NDEBUG 0
#include "EngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
#include <cutils/properties.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
#include <media/TypeConverter.h>
#include <media/convert.h>
#include <system/audio_config.h>
#include <utils/Log.h>
-#include <libxml/parser.h>
-#include <libxml/xinclude.h>
-#include <string>
-#include <vector>
-#include <map>
-#include <sstream>
-#include <istream>
-
-#include <cstdint>
-#include <stdarg.h>
-#include <string>
namespace android {
@@ -45,6 +49,85 @@
static const char *const gReferenceElementName = "reference";
static const char *const gReferenceAttributeName = "name";
+namespace {
+
+ConversionResult<AttributesGroup> aidl2legacy_AudioHalAttributeGroup_AttributesGroup(
+ const media::audio::common::AudioHalAttributesGroup& aidl) {
+ AttributesGroup legacy;
+ legacy.stream = VALUE_OR_RETURN(
+ aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+ legacy.volumeGroup = aidl.volumeGroupName;
+ legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
+ aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
+ return legacy;
+}
+
+ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
+ const media::audio::common::AudioHalProductStrategy& aidl) {
+ ProductStrategy legacy;
+ legacy.name = "strategy_" + std::to_string(aidl.id);
+ legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
+ aidl.attributesGroups,
+ aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
+ return legacy;
+}
+
+ConversionResult<std::string> legacy_device_category_to_string(device_category legacy) {
+ std::string s;
+ if (DeviceCategoryConverter::toString(legacy, s)) {
+ return s;
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::string> aidl2legacy_DeviceCategory(
+ const media::audio::common::AudioHalVolumeCurve::DeviceCategory aidl) {
+ using DeviceCategory = media::audio::common::AudioHalVolumeCurve::DeviceCategory;
+ switch (aidl) {
+ case DeviceCategory::HEADSET:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_HEADSET);
+ case DeviceCategory::SPEAKER:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_SPEAKER);
+ case DeviceCategory::EARPIECE:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_EARPIECE);
+ case DeviceCategory::EXT_MEDIA:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_EXT_MEDIA);
+ case DeviceCategory::HEARING_AID:
+ return legacy_device_category_to_string(DEVICE_CATEGORY_HEARING_AID);
+ }
+ return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<CurvePoint> aidl2legacy_AudioHalCurvePoint_CurvePoint(
+ const media::audio::common::AudioHalVolumeCurve::CurvePoint& aidl) {
+ CurvePoint legacy;
+ legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+ legacy.attenuationInMb = aidl.attenuationMb;
+ return legacy;
+}
+
+ConversionResult<VolumeCurve> aidl2legacy_AudioHalVolumeCurve_VolumeCurve(
+ const media::audio::common::AudioHalVolumeCurve& aidl) {
+ VolumeCurve legacy;
+ legacy.deviceCategory = VALUE_OR_RETURN(aidl2legacy_DeviceCategory(aidl.deviceCategory));
+ legacy.curvePoints = VALUE_OR_RETURN(convertContainer<CurvePoints>(
+ aidl.curvePoints, aidl2legacy_AudioHalCurvePoint_CurvePoint));
+ return legacy;
+}
+
+ConversionResult<VolumeGroup> aidl2legacy_AudioHalVolumeGroup_VolumeGroup(
+ const media::audio::common::AudioHalVolumeGroup& aidl) {
+ VolumeGroup legacy;
+ legacy.name = aidl.name;
+ legacy.indexMin = aidl.minIndex;
+ legacy.indexMax = aidl.maxIndex;
+ legacy.volumeCurves = VALUE_OR_RETURN(convertContainer<VolumeCurves>(
+ aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
+ return legacy;
+}
+
+} // namespace
+
template<typename E, typename C>
struct BaseSerializerTraits {
typedef E Element;
@@ -724,5 +807,25 @@
}
}
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ auto config = std::make_unique<engineConfig::Config>();
+ config->version = 1.0f;
+ if (auto conv = convertContainer<engineConfig::ProductStrategies>(
+ aidlConfig.productStrategies,
+ aidl2legacy_AudioHalProductStrategy_ProductStrategy); conv.ok()) {
+ config->productStrategies = std::move(conv.value());
+ } else {
+ return ParsingResult{};
+ }
+ if (auto conv = convertContainer<engineConfig::VolumeGroups>(
+ aidlConfig.volumeGroups,
+ aidl2legacy_AudioHalVolumeGroup_VolumeGroup); conv.ok()) {
+ config->volumeGroups = std::move(conv.value());
+ } else {
+ return ParsingResult{};
+ }
+ return {.parsedConfig=std::move(config), .nbSkippedElement=0};
+ }
+
} // namespace engineConfig
} // namespace android
diff --git a/services/audiopolicy/engine/config/tests/Android.bp b/services/audiopolicy/engine/config/tests/Android.bp
index 5791f17..5d1aa16 100644
--- a/services/audiopolicy/engine/config/tests/Android.bp
+++ b/services/audiopolicy/engine/config/tests/Android.bp
@@ -11,6 +11,7 @@
name: "audiopolicy_engineconfig_tests",
shared_libs: [
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libmedia_helper",
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index dd7ac1a..70461ad 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -20,6 +20,7 @@
#include <utility>
#include <AudioPolicyManagerObserver.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
#include <media/AudioProductStrategy.h>
#include <media/AudioVolumeGroup.h>
#include <IVolumeCurves.h>
@@ -47,6 +48,14 @@
{
public:
/**
+ * Loads the engine configuration from AIDL configuration data.
+ * If loading failed, tries to fall back to some default configuration. If fallback
+ * is impossible, returns an error.
+ */
+ virtual status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) = 0;
+
+ /**
* Loads the engine configuration from the specified or the default config file.
* If loading failed, tries to fall back to some default configuration. If fallback
* is impossible, returns an error.
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index dc8d9cf..eb2e2f4 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -35,14 +35,15 @@
"libaudiopolicyengineconfigurable_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
"libaudiopolicyengineconfigurable_pfwwrapper",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libcutils",
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index 0398fc7..f7159c5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -31,11 +31,11 @@
"libaudiopolicyengineconfigurable_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libpfw_utility",
],
shared_libs: [
+ "libaudiopolicycomponents",
"libaudiopolicyengineconfigurable",
"liblog",
"libutils",
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 2eb0177..ccd4316 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -70,6 +70,12 @@
{
}
+status_t Engine::loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config __unused) {
+ // b/242678729. Need to implement for the configurable engine.
+ return INVALID_OPERATION;
+}
+
status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
{
status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index b964cd6..4f3e620 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -41,12 +41,15 @@
///
/// from EngineInterface
///
- android::status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+ status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) override;
+
+ status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
///
/// from EngineBase
///
- android::status_t initCheck() override;
+ status_t initCheck() override;
status_t setPhoneState(audio_mode_t mode) override;
@@ -56,8 +59,8 @@
audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const override;
- android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
- audio_policy_dev_state_t state) override;
+ status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+ audio_policy_dev_state_t state) override;
DeviceVector getOutputDevicesForAttributes(const audio_attributes_t &attr,
const sp<DeviceDescriptor> &preferedDevice = nullptr,
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index 4671fe9..7d4ccab 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -25,12 +25,13 @@
"libaudiopolicyengine_interface_headers",
],
static_libs: [
- "libaudiopolicycomponents",
"libaudiopolicyengine_common",
"libaudiopolicyengine_config",
],
shared_libs: [
+ "libaudio_aidl_conversion_common_cpp",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"liblog",
"libcutils",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 88cbb7d..15f7842 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -35,10 +35,7 @@
#include <utils/String8.h>
#include <utils/Log.h>
-namespace android
-{
-namespace audio_policy
-{
+namespace android::audio_policy {
struct legacy_strategy_map { const char *name; legacy_strategy id; };
static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
@@ -59,8 +56,18 @@
return legacyStrategy;
}
+status_t Engine::loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& aidlConfig) {
+ return loadWithFallback(aidlConfig);
+}
+
status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
- auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
+ return loadWithFallback(xmlFilePath);
+}
+
+template<typename T>
+status_t Engine::loadWithFallback(const T& configSource) {
+ auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
ALOGE_IF(result.nbSkippedElement != 0,
"Policy Engine configuration is partially invalid, skipped %zu elements",
result.nbSkippedElement);
@@ -73,6 +80,7 @@
return OK;
}
+
status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
switch(usage) {
@@ -844,5 +852,4 @@
AUDIO_FORMAT_DEFAULT);
}
-} // namespace audio_policy
-} // namespace android
+} // namespace android::audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 8410560..878bca9 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -47,10 +47,14 @@
public:
Engine() = default;
virtual ~Engine() = default;
+ Engine(const Engine &object) = delete;
+ Engine &operator=(const Engine &object) = delete;
///
/// from EngineInterface
///
+ status_t loadFromHalConfigWithFallback(
+ const media::audio::common::AudioHalEngineConfig& config) override;
status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
private:
@@ -79,9 +83,8 @@
DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
private:
- /* Copy facilities are put private to disable copy. */
- Engine(const Engine &object);
- Engine &operator=(const Engine &object);
+ template<typename T>
+ status_t loadWithFallback(const T& configSource);
status_t setDefaultDevice(audio_devices_t device);
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 621f643..c4b3751 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -38,6 +38,7 @@
"capture_state_listener-aidl-cpp",
"libaudioclient",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libbase",
"libcutils",
"libhidlbase",
@@ -54,7 +55,6 @@
],
static_libs: [
"android.hardware.audio.common@7.0-enums",
- "libaudiopolicycomponents",
],
header_libs: [
"libaudiopolicycommon",
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 6e34eb0..a1785da 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -23,6 +23,7 @@
shared_libs: [
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libcutils",
"libdl",
"libutils",
@@ -49,8 +50,6 @@
"libaudiopolicymanager_interface_headers",
],
- static_libs: ["libaudiopolicycomponents"],
-
cflags: [
"-Wall",
"-Werror",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f093e68..a0ec9aa 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1106,7 +1106,12 @@
// and AudioSystem::getOutputSamplingRate().
SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
- const audio_io_handle_t output = selectOutput(outputs);
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ if (stream == AUDIO_STREAM_MUSIC &&
+ property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
+ flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+ }
+ const audio_io_handle_t output = selectOutput(outputs, flags);
ALOGV("getOutput() stream %d selected devices %s, output %d", stream,
devices.toString().c_str(), output);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index 939fbc5..ab77941 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -40,6 +40,23 @@
return engine;
}
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const media::audio::common::AudioHalEngineConfig& config)
+{
+ auto engLib = EngineLibrary::load(librarySuffix);
+ if (!engLib) {
+ ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
+ __func__, librarySuffix.c_str());
+ return nullptr;
+ }
+ auto engine = engLib->createEngineUsingHalConfig(config);
+ if (engine == nullptr) {
+ ALOGE("%s: Failed to instantiate the APM engine", __func__);
+ return nullptr;
+ }
+ return engine;
+}
+
// static
std::shared_ptr<EngineLibrary> EngineLibrary::load(const std::string& librarySuffix)
{
@@ -53,7 +70,8 @@
close();
}
-EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath) {
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath)
+{
auto instance = createEngine();
if (instance != nullptr) {
if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
@@ -67,6 +85,21 @@
return nullptr;
}
+EngineInstance EngineLibrary::createEngineUsingHalConfig(
+ const media::audio::common::AudioHalEngineConfig& config)
+{
+ auto instance = createEngine();
+ if (instance != nullptr) {
+ if (status_t status = instance->loadFromHalConfigWithFallback(config); status == OK) {
+ return instance;
+ } else {
+ ALOGE("%s: loading of the engine config with HAL configuration \"%s\" failed: %d",
+ __func__, config.toString().c_str(), status);
+ }
+ }
+ return nullptr;
+}
+
bool EngineLibrary::init(std::string libraryPath)
{
mLibraryHandle = dlopen(libraryPath.c_str(), 0);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
index dc138a1..4710e34 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -21,6 +21,7 @@
#include <string>
#include <EngineInterface.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
namespace android {
@@ -28,6 +29,8 @@
EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
const std::string& configXmlFilePath = "");
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+ const media::audio::common::AudioHalEngineConfig& config);
class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
public:
@@ -40,6 +43,8 @@
EngineLibrary& operator=(EngineLibrary&&) = delete;
EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
+ EngineInstance createEngineUsingHalConfig(
+ const media::audio::common::AudioHalEngineConfig& config);
private:
EngineLibrary() = default;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 2f677da..f4fc8f1 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -35,6 +35,7 @@
"libaudiofoundation",
"libaudiohal",
"libaudiopolicy",
+ "libaudiopolicycomponents",
"libaudiopolicymanagerdefault",
"libaudiousecasevalidation",
"libaudioutils",
@@ -66,7 +67,6 @@
],
static_libs: [
- "libaudiopolicycomponents",
"framework-permission-aidl-cpp",
],
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 2e7b3ff..5d86e7c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -318,7 +318,7 @@
return Status::ok();
}
-Status AudioPolicyService::getOutputForAttr(const media::AudioAttributesInternal& attrAidl,
+Status AudioPolicyService::getOutputForAttr(const media::audio::common::AudioAttributes& attrAidl,
int32_t sessionAidl,
const AttributionSourceState& attributionSource,
const AudioConfig& configAidl,
@@ -327,7 +327,7 @@
media::GetOutputForAttrResponse* _aidl_return)
{
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_session_t(sessionAidl));
audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
@@ -440,7 +440,7 @@
_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 @@
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 @@
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::setVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
const AudioDeviceDescription& deviceAidl, int32_t indexAidl) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
@@ -1096,10 +1096,10 @@
}
Status AudioPolicyService::getVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
const AudioDeviceDescription& deviceAidl, int32_t* _aidl_return) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
int index;
@@ -1118,9 +1118,9 @@
}
Status AudioPolicyService::getMinVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl, int32_t* _aidl_return) {
+ const media::audio::common::AudioAttributes& attrAidl, int32_t* _aidl_return) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1137,9 +1137,9 @@
}
Status AudioPolicyService::getMaxVolumeIndexForAttributes(
- const media::AudioAttributesInternal& attrAidl, int32_t* _aidl_return) {
+ const media::audio::common::AudioAttributes& attrAidl, int32_t* _aidl_return) {
audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
int index;
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1177,12 +1177,13 @@
return Status::ok();
}
-Status AudioPolicyService::getDevicesForAttributes(const media::AudioAttributesInternal& attrAidl,
- bool forVolume,
- std::vector<AudioDevice>* _aidl_return)
+Status AudioPolicyService::getDevicesForAttributes(
+ const media::audio::common::AudioAttributes& attrAidl,
+ bool forVolume,
+ std::vector<AudioDevice>* _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::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::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::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::getVolumeGroupFromAudioAttributes(
- 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));
volume_group_t volumeGroup;
if (mAudioPolicyManager == NULL) {
@@ -2381,7 +2382,7 @@
}
Status AudioPolicyService::canBeSpatialized(
- const std::optional<media::AudioAttributesInternal>& attrAidl,
+ const std::optional<media::audio::common::AudioAttributes>& attrAidl,
const std::optional<AudioConfig>& configAidl,
const std::vector<AudioDevice>& devicesAidl,
bool* _aidl_return) {
@@ -2391,7 +2392,7 @@
audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
if (attrAidl.has_value()) {
attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl.value()));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl.value()));
}
audio_config_t config = AUDIO_CONFIG_INITIALIZER;
if (configAidl.has_value()) {
@@ -2408,9 +2409,10 @@
return Status::ok();
}
-Status AudioPolicyService::getDirectPlaybackSupport(const media::AudioAttributesInternal &attrAidl,
- const AudioConfig &configAidl,
- media::AudioDirectMode *_aidl_return) {
+Status AudioPolicyService::getDirectPlaybackSupport(
+ const media::audio::common::AudioAttributes &attrAidl,
+ const AudioConfig &configAidl,
+ media::AudioDirectMode *_aidl_return) {
if (mAudioPolicyManager == nullptr) {
return binderStatusFromStatusT(NO_INIT);
}
@@ -2418,7 +2420,7 @@
return binderStatusFromStatusT(BAD_VALUE);
}
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
audio_config_t config = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioConfig_audio_config_t(configAidl, false /*isInput*/));
Mutex::Autolock _l(mLock);
@@ -2429,13 +2431,13 @@
}
Status AudioPolicyService::getDirectProfilesForAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
std::vector<media::audio::common::AudioProfile>* _aidl_return) {
if (mAudioPolicyManager == nullptr) {
return binderStatusFromStatusT(NO_INIT);
}
audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+ aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
AudioProfileVector audioProfiles;
Mutex::Autolock _l(mLock);
@@ -2470,7 +2472,7 @@
}
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 @@
}
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::getPreferredMixerAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
int32_t portIdAidl,
std::optional<media::AudioMixerAttributesInternal>* _aidl_return) {
if (mAudioPolicyManager == nullptr) {
@@ -2500,7 +2502,7 @@
}
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::clearPreferredMixerAttributes(
- const media::AudioAttributesInternal& attrAidl,
+ const media::audio::common::AudioAttributes& attrAidl,
int32_t portIdAidl,
int32_t uidAidl) {
if (mAudioPolicyManager == nullptr) {
@@ -2523,7 +2525,7 @@
}
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.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 9367949..234104d 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -186,10 +186,23 @@
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
- auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
- AudioPolicyManager *apm = new AudioPolicyManager(
- config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
- clientInterface);
+ AudioPolicyManager *apm = nullptr;
+ media::AudioPolicyConfig apmConfig;
+ if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
+ auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
+ LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
+ AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
+ "Only default engine is currently supported with the AIDL HAL");
+ apm = new AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(
+ config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
+ clientInterface);
+ } else {
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(); // This can't fail.
+ apm = new AudioPolicyManager(config,
+ loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+ clientInterface);
+ }
status_t status = apm->initialize();
if (status != NO_ERROR) {
delete apm;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 4710a8a..d0cde64 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -98,7 +98,8 @@
binder::Status getForceUse(media::AudioPolicyForceUse usage,
media::AudioPolicyForcedConfig* _aidl_return) override;
binder::Status getOutput(AudioStreamType stream, int32_t* _aidl_return) override;
- binder::Status getOutputForAttr(const media::AudioAttributesInternal& attr, int32_t session,
+ binder::Status getOutputForAttr(const media::audio::common::AudioAttributes& attr,
+ int32_t session,
const AttributionSourceState &attributionSource,
const AudioConfig& config,
int32_t flags, int32_t selectedDeviceId,
@@ -106,7 +107,7 @@
binder::Status startOutput(int32_t portId) override;
binder::Status stopOutput(int32_t portId) override;
binder::Status releaseOutput(int32_t portId) override;
- binder::Status getInputForAttr(const media::AudioAttributesInternal& attr, int32_t input,
+ binder::Status getInputForAttr(const media::audio::common::AudioAttributes& attr, int32_t input,
int32_t riid, int32_t session,
const AttributionSourceState &attributionSource,
const AudioConfigBase& config, int32_t flags,
@@ -123,19 +124,19 @@
binder::Status getStreamVolumeIndex(AudioStreamType stream,
const AudioDeviceDescription& device,
int32_t* _aidl_return) override;
- binder::Status setVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status setVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
const AudioDeviceDescription& device,
int32_t index) override;
- binder::Status getVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
const AudioDeviceDescription& device,
int32_t* _aidl_return) override;
- binder::Status getMaxVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getMaxVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
int32_t* _aidl_return) override;
- binder::Status getMinVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getMinVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
int32_t* _aidl_return) override;
binder::Status getStrategyForStream(AudioStreamType stream,
int32_t* _aidl_return) override;
- binder::Status getDevicesForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getDevicesForAttributes(const media::audio::common::AudioAttributes& attr,
bool forVolume,
std::vector<AudioDevice>* _aidl_return) override;
binder::Status getOutputForEffect(const media::EffectDescriptor& desc,
@@ -170,7 +171,7 @@
binder::Status getOffloadSupport(const media::audio::common::AudioOffloadInfo& info,
media::AudioOffloadMode* _aidl_return) override;
binder::Status isDirectOutputSupported(const AudioConfigBase& config,
- const media::AudioAttributesInternal& attributes,
+ const media::audio::common::AudioAttributes& attributes,
bool* _aidl_return) override;
binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
Int* count, std::vector<media::AudioPortFw>* ports,
@@ -201,7 +202,7 @@
const std::vector<AudioDevice>& devices) override;
binder::Status removeUserIdDeviceAffinities(int32_t userId) override;
binder::Status startAudioSource(const media::AudioPortConfigFw& source,
- const media::AudioAttributesInternal& attributes,
+ const media::audio::common::AudioAttributes& attributes,
int32_t* _aidl_return) override;
binder::Status stopAudioSource(int32_t portId) override;
binder::Status setMasterMono(bool mono) override;
@@ -228,14 +229,16 @@
binder::Status isHotwordStreamSupported(bool lookbackAudio, bool* _aidl_return) override;
binder::Status listAudioProductStrategies(
std::vector<media::AudioProductStrategy>* _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<media::AudioVolumeGroup>* _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 @@
binder::Status getSpatializer(const sp<media::INativeSpatializerCallback>& callback,
media::GetSpatializerResponse* _aidl_return) override;
binder::Status canBeSpatialized(
- const std::optional<media::AudioAttributesInternal>& attr,
+ const std::optional<media::audio::common::AudioAttributes>& attr,
const std::optional<AudioConfig>& config,
const std::vector<AudioDevice>& devices,
bool* _aidl_return) override;
- binder::Status getDirectPlaybackSupport(const media::AudioAttributesInternal& attr,
+ binder::Status getDirectPlaybackSupport(const media::audio::common::AudioAttributes& attr,
const AudioConfig& config,
media::AudioDirectMode* _aidl_return) override;
- binder::Status getDirectProfilesForAttributes(const media::AudioAttributesInternal& attr,
+ binder::Status getDirectProfilesForAttributes(const media::audio::common::AudioAttributes& attr,
std::vector<media::audio::common::AudioProfile>* _aidl_return) override;
binder::Status getSupportedMixerAttributes(
int32_t portId,
std::vector<media::AudioMixerAttributesInternal>* _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<media::AudioMixerAttributesInternal>* _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;
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index ee2e0eb..1245b1e 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -236,18 +236,15 @@
sp<EffectHalInterface> 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());
}
}
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 285b354..a4a0cd4 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -78,6 +78,7 @@
"libaudioclient",
"libaudioclient_aidl_conversion",
"libaudiofoundation",
+ "libaudiopolicycomponents",
"libaudiopolicymanagerdefault",
"libcutils",
"liblog",
@@ -89,8 +90,6 @@
"libxml2",
],
- static_libs: ["libaudiopolicycomponents"],
-
header_libs: [
"libaudiopolicyengine_interface_headers",
"libaudiopolicymanager_interface_headers",
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
index 9475a39..f39599f 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.h
@@ -113,7 +113,7 @@
static const nsecs_t kWaitDuration = 100000000; // 100 ms
static const nsecs_t kIdleWaitDuration = 10000000; // 10 ms
static const int kMaxTimeoutsForPrecaptureStart = 10; // 1 sec
- static const int kMaxTimeoutsForPrecaptureEnd = 20; // 2 sec
+ static const int kMaxTimeoutsForPrecaptureEnd = 40; // 4 sec
static const int kMaxTimeoutsForCaptureEnd = 40; // 4 sec
static const int kMaxRetryCount = 3; // 3 retries in case of buffer drop
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index fac6e4e..1a6e341 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -2530,7 +2530,11 @@
const CameraResourceCost& resourceCost,
sp<ProviderInfo> parentProvider,
const std::vector<std::string>& publicCameraIds) :
- DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
+ DeviceInfo(name, tagId, id,
+ hardware::hidl_version{
+ static_cast<uint16_t >(
+ parentProvider->getIPCTransport() == IPCTransport::HIDL ? 3 : 1),
+ minorVersion},
publicCameraIds, resourceCost, parentProvider) { }
void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(int64_t newState) {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index b1bf41e..921ad7d 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -29,11 +29,8 @@
],
}
-cc_fuzz {
- name: "camera_service_fuzzer",
- srcs: [
- "camera_service_fuzzer.cpp",
- ],
+cc_defaults {
+ name: "camera_service_fuzzer_defaults",
header_libs: [
"libmedia_headers",
],
@@ -74,3 +71,28 @@
},
}
+
+cc_fuzz {
+ name: "camera_service_fuzzer",
+ srcs: [
+ "camera_service_fuzzer.cpp",
+ ],
+ defaults: [
+ "camera_service_fuzzer_defaults"
+ ],
+}
+
+cc_fuzz {
+ name: "camera_service_aidl_fuzzer",
+ srcs: [
+ "camera_service_aidl_fuzzer.cpp",
+ ],
+ defaults: [
+ "camera_service_fuzzer_defaults",
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ ],
+ fuzz_config: {
+ triage_assignee: "waghpawan@google.com",
+ },
+}
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp
new file mode 100644
index 0000000..a0fb93c
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fuzzbinder/libbinder_driver.h>
+#include <CameraService.h>
+
+using android::fuzzService;
+using android::sp;
+using android::CameraService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<CameraService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index acafe56..e22d749 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -89,3 +89,25 @@
"code_coverage.policy",
],
}
+
+cc_fuzz {
+ name: "mediaextractor_service_fuzzer",
+ shared_libs: [
+ "libmedia",
+ "libmediaextractorservice",
+ "libmediautils",
+ "liblog",
+ "libavservices_minijail",
+ ],
+ defaults: [
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ ],
+ srcs: ["fuzzers/MediaExtractorServiceFuzzer.cpp"],
+ fuzz_config: {
+ cc: [
+ "android-media-playback+bugs@google.com",
+ ],
+ triage_assignee: "waghpawan@google.com",
+ },
+}
\ No newline at end of file
diff --git a/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
new file mode 100644
index 0000000..d329e54
--- /dev/null
+++ b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include "MediaExtractorService.h"
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaExtractorService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<MediaExtractorService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 20a6378..99703e3 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -27,13 +27,8 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_fuzz {
- name: "mediametrics_service_fuzzer",
-
- srcs: [
- "mediametrics_service_fuzzer.cpp",
- ],
-
+cc_defaults {
+ name: "mediametrics_service_fuzzer_defaults",
static_libs: [
"libmediametrics",
"libmediametricsservice",
@@ -78,3 +73,26 @@
fuzzed_code_usage: "shipped",
},
}
+
+cc_fuzz {
+ name: "mediametrics_service_fuzzer",
+
+ srcs: [
+ "mediametrics_service_fuzzer.cpp",
+ ],
+ defaults: [
+ "mediametrics_service_fuzzer_defaults",
+ ],
+}
+
+cc_fuzz {
+ name: "mediametrics_aidl_fuzzer",
+ srcs: [
+ "mediametrics_aidl_fuzzer.cpp",
+ ],
+ defaults: [
+ "service_fuzzer_defaults",
+ "fuzzer_disable_leaks",
+ "mediametrics_service_fuzzer_defaults",
+ ],
+}
diff --git a/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
new file mode 100644
index 0000000..c7468c7
--- /dev/null
+++ b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include <mediametricsservice/MediaMetricsService.h>
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaMetricsService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = sp<MediaMetricsService>::make();
+ fuzzService(service, FuzzedDataProvider(data, size));
+ return 0;
+}