Merge "SpatializerPoseController: Fix destruction order" into udc-dev
diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
new file mode 100644
index 0000000..36f6128
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
@@ -0,0 +1,128 @@
+/*
+ * 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 <algorithm>
+#include <type_traits>
+
+#define LOG_TAG "AidlConversionNdkCpp"
+#include <utils/Log.h>
+
+#include <android-base/expected.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_parcel.h>
+#include <binder/Enums.h>
+#include <media/AidlConversionNdkCpp.h>
+#include <media/AidlConversionUtil.h>
+
+using aidl::android::aidl_utils::statusTFromBinderStatusT;
+
+namespace android {
+
+namespace {
+
+// 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.
+
+template<typename NdkType, typename CppType>
+ConversionResult<NdkType> cpp2ndk(const CppType& cpp) {
+ Parcel cppParcel;
+ RETURN_IF_ERROR(cpp.writeToParcel(&cppParcel));
+ ::ndk::ScopedAParcel ndkParcel(AParcel_create());
+ const int32_t ndkParcelBegin = AParcel_getDataPosition(ndkParcel.get());
+ RETURN_IF_ERROR(statusTFromBinderStatusT(AParcel_unmarshal(
+ ndkParcel.get(), cppParcel.data(), cppParcel.dataSize())));
+ RETURN_IF_ERROR(statusTFromBinderStatusT(AParcel_setDataPosition(
+ ndkParcel.get(), ndkParcelBegin)));
+ NdkType ndk;
+ RETURN_IF_ERROR(statusTFromBinderStatusT(ndk.readFromParcel(ndkParcel.get())));
+ return ndk;
+}
+
+template<typename CppType, typename NdkType>
+ConversionResult<CppType> ndk2cpp(const NdkType& ndk) {
+ ::ndk::ScopedAParcel ndkParcel(AParcel_create());
+ RETURN_IF_ERROR(statusTFromBinderStatusT(ndk.writeToParcel(ndkParcel.get())));
+ const int32_t ndkParcelDataSize = AParcel_getDataSize(ndkParcel.get());
+ if (ndkParcelDataSize < 0) {
+ return base::unexpected(BAD_VALUE);
+ }
+ // Parcel does not expose its data in a mutable form, we have to use an intermediate buffer.
+ std::vector<uint8_t> parcelData(static_cast<size_t>(ndkParcelDataSize));
+ RETURN_IF_ERROR(statusTFromBinderStatusT(AParcel_marshal(
+ ndkParcel.get(), parcelData.data(), 0, ndkParcelDataSize)));
+ Parcel cppParcel;
+ RETURN_IF_ERROR(cppParcel.setData(parcelData.data(), parcelData.size()));
+ CppType cpp;
+ RETURN_IF_ERROR(cpp.readFromParcel(&cppParcel));
+ return cpp;
+}
+
+// cpp2ndk_Enum and ndk2cpp_Enum are more efficient implementations specifically for enums.
+
+template<typename OutEnum, typename OutEnumRange, typename InEnum>
+ ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
+ using InIntType = std::underlying_type_t<InEnum>;
+ static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
+
+ InIntType inEnumIndex = static_cast<InIntType>(e);
+ OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
+ if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
+ return base::unexpected(BAD_VALUE);
+ }
+ return outEnum;
+}
+
+template<typename NdkEnum, typename CppEnum>
+ ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum cpp) {
+ return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), cpp);
+}
+
+template<typename CppEnum, typename NdkEnum>
+ ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum ndk) {
+ return convertEnum<CppEnum>(enum_range<CppEnum>(), ndk);
+}
+
+} // namespace
+
+#define GENERATE_CONVERTERS(packageName, className) \
+ ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+ const ::packageName::className& cpp) { \
+ return cpp2ndk<::aidl::packageName::className>(cpp); \
+ } \
+ ConversionResult<::packageName::className> ndk2cpp_##className( \
+ const ::aidl::packageName::className& ndk) { \
+ return ndk2cpp<::packageName::className>(ndk); \
+ }
+
+#define GENERATE_ENUM_CONVERTERS(packageName, className) \
+ ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+ const ::packageName::className& cpp) { \
+ return cpp2ndk_Enum<::aidl::packageName::className>(cpp); \
+ } \
+ ConversionResult<::packageName::className> ndk2cpp_##className( \
+ const ::aidl::packageName::className& ndk) { \
+ return ndk2cpp_Enum<::packageName::className>(ndk); \
+}
+
+GENERATE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
+GENERATE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+GENERATE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
+GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+GENERATE_CONVERTERS(android::media::audio::common, AudioPort);
+
+} // namespace android
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index 1ec4849..d3a5755 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -212,3 +212,27 @@
],
min_sdk_version: "31", //AParcelableHolder has been introduced in 31
}
+
+/**
+ * Conversions between the NDK and CPP backends for common types.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_common_ndk_cpp",
+ srcs: [
+ "AidlConversionNdkCpp.cpp",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "audio_aidl_conversion_common_util_default",
+ "latest_android_media_audio_common_types_cpp_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libbase",
+ ],
+ cflags: [
+ "-DBACKEND_CPP_NDK",
+ ],
+ min_sdk_version: "33", //AParcel_unmarshal has been introduced in 33
+}
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index a0c9759..903b88a 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,7 +1,8 @@
{
"presubmit": [
{
- "name": "audio_aidl_ndk_conversion_tests"
+ "name": "audio_aidl_ndk_conversion_tests",
+ "name": "audio_aidl_ndk_cpp_conversion_tests"
}
]
}
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
new file mode 100644
index 0000000..09f1c22
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**
+ * Conversions between the NDK and CPP backends for common types.
+ */
+#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <aidl/android/media/audio/common/AudioMMapPolicyInfo.h>
+#include <aidl/android/media/audio/common/AudioMMapPolicyType.h>
+#include <aidl/android/media/audio/common/AudioPort.h>
+#include <android/media/audio/common/AudioFormatDescription.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <android/media/audio/common/AudioMMapPolicyInfo.h>
+#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioPort.h>
+#include <media/AidlConversionUtil.h>
+
+namespace android {
+
+#define DECLARE_CONVERTERS(packageName, className) \
+ ConversionResult<::aidl::packageName::className> \
+ cpp2ndk_##className(const ::packageName::className& cpp); \
+ ConversionResult<::packageName::className> \
+ ndk2cpp_##className(const ::aidl::packageName::className& ndk);
+
+DECLARE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
+DECLARE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+DECLARE_CONVERTERS(android::media::audio::common, AudioPort);
+
+#undef DECLARE_CONVERTERS
+
+} // namespace android
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index b179cbb..f49f681 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -389,6 +389,10 @@
?: statusTFromExceptionCode(status.getExceptionCode()); // a service-side error with a
// standard Java exception (fromExceptionCode)
}
+
+static inline ::android::status_t statusTFromBinderStatusT(binder_status_t status) {
+ return statusTFromBinderStatus(::ndk::ScopedAStatus::fromStatus(status));
+}
#endif
/**
diff --git a/media/audioaidlconversion/tests/Android.bp b/media/audioaidlconversion/tests/Android.bp
index de7c8a2..88b2cc9 100644
--- a/media/audioaidlconversion/tests/Android.bp
+++ b/media/audioaidlconversion/tests/Android.bp
@@ -44,3 +44,27 @@
"-DBACKEND_NDK",
],
}
+
+cc_test {
+ name: "audio_aidl_ndk_cpp_conversion_tests",
+
+ defaults: [
+ "latest_android_media_audio_common_types_cpp_static",
+ "latest_android_media_audio_common_types_ndk_static",
+ "libaudio_aidl_conversion_tests_defaults",
+ ],
+ srcs: ["audio_aidl_ndk_cpp_conversion_tests.cpp"],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "libaudio_aidl_conversion_common_ndk_cpp",
+ ],
+ cflags: [
+ "-DBACKEND_CPP_NDK",
+ ],
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
new file mode 100644
index 0000000..735a14b
--- /dev/null
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
@@ -0,0 +1,127 @@
+/*
+ * 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 <iostream>
+#include <type_traits>
+
+#include <gtest/gtest.h>
+
+#include <media/AidlConversionNdkCpp.h>
+
+namespace {
+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
+#define DEFINE_PRINTING_TEMPLATES()
+ 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::media::audio::common {
+DEFINE_PRINTING_TEMPLATES();
+} // namespace aidl::android::media::audio::common
+namespace android::hardware::audio::common {
+DEFINE_PRINTING_TEMPLATES();
+} // namespace android::hardware::audio::common
+#undef DEFINE_PRINTING_TEMPLATES
+
+using namespace android;
+
+namespace {
+
+using namespace ::aidl::android::media::audio::common;
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+ AudioFormatDescription result;
+ result.type = type;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+ auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+ result.pcm = pcm;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+ AudioFormatDescription result;
+ result.encoding = encoding;
+ return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport, const std::string& encoding) {
+ auto result = make_AudioFormatDescription(encoding);
+ result.pcm = transport;
+ return result;
+}
+
+AudioFormatDescription make_AFD_Default() {
+ return AudioFormatDescription{};
+}
+
+AudioFormatDescription make_AFD_Invalid() {
+ return make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID);
+}
+
+AudioFormatDescription make_AFD_Pcm16Bit() {
+ return make_AudioFormatDescription(PcmType::INT_16_BIT);
+}
+
+AudioFormatDescription make_AFD_Bitstream() {
+ return make_AudioFormatDescription("example");
+}
+
+AudioFormatDescription make_AFD_Encap() {
+ return make_AudioFormatDescription(PcmType::INT_16_BIT, "example.encap");
+}
+
+AudioFormatDescription make_AFD_Encap_with_Enc() {
+ auto afd = make_AFD_Encap();
+ afd.encoding += "+example";
+ return afd;
+}
+
+} // namespace
+
+// There is no reason to write test for every type which gets converted via parcelable
+// since the conversion code is all the same.
+
+class AudioFormatDescriptionRoundTripTest :
+ public testing::TestWithParam<::aidl::android::media::audio::common::AudioFormatDescription>
+{
+};
+TEST_P(AudioFormatDescriptionRoundTripTest, Ndk2Cpp2Ndk) {
+ const auto& initial = GetParam();
+ auto conv = ndk2cpp_AudioFormatDescription(initial);
+ ASSERT_TRUE(conv.ok());
+ auto convBack = cpp2ndk_AudioFormatDescription(conv.value());
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+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()));
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index fc8ba9e..67ee42e 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -132,10 +132,11 @@
AAudioConvert_contentTypeToInternal(builder.getContentType());
const audio_usage_t usage =
AAudioConvert_usageToInternal(builder.getUsage());
- const audio_flags_mask_t attributesFlags =
- AAudioConvert_allowCapturePolicyToAudioFlagsMask(builder.getAllowedCapturePolicy(),
- builder.getSpatializationBehavior(),
- builder.isContentSpatialized());
+ const audio_flags_mask_t attributesFlags = AAudio_computeAudioFlagsMask(
+ builder.getAllowedCapturePolicy(),
+ builder.getSpatializationBehavior(),
+ builder.isContentSpatialized(),
+ flags);
const audio_attributes_t attributes = {
.content_type = contentType,
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index 8920e53..e8324a8 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -255,10 +255,11 @@
return (audio_source_t) preset; // same value
}
-audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+audio_flags_mask_t AAudio_computeAudioFlagsMask(
aaudio_allowed_capture_policy_t policy,
aaudio_spatialization_behavior_t spatializationBehavior,
- bool isContentSpatialized) {
+ bool isContentSpatialized,
+ audio_output_flags_t outputFlags) {
audio_flags_mask_t flagsMask = AUDIO_FLAG_NONE;
switch (policy) {
case AAUDIO_UNSPECIFIED:
@@ -295,6 +296,15 @@
flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_CONTENT_SPATIALIZED);
}
+ if ((outputFlags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+ flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_HW_AV_SYNC);
+ }
+ if ((outputFlags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
+ flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_LOW_LATENCY);
+ } else if ((outputFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
+ flagsMask = static_cast<audio_flags_mask_t>(flagsMask | AUDIO_FLAG_DEEP_BUFFER);
+ }
+
return flagsMask;
}
diff --git a/media/libaaudio/src/utility/AAudioUtilities.h b/media/libaaudio/src/utility/AAudioUtilities.h
index d8e5b00..d44bbab 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.h
+++ b/media/libaaudio/src/utility/AAudioUtilities.h
@@ -94,10 +94,11 @@
* That is done somewhere else.
* @return internal audio flags mask
*/
-audio_flags_mask_t AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+audio_flags_mask_t AAudio_computeAudioFlagsMask(
aaudio_allowed_capture_policy_t policy,
aaudio_spatialization_behavior_t spatializationBehavior,
- bool isContentSpatialized);
+ bool isContentSpatialized,
+ audio_output_flags_t outputFlags);
audio_flags_mask_t AAudioConvert_privacySensitiveToAudioFlagsMask(
bool privacySensitive);
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 2bbfb76..d5bbb52 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -300,11 +300,14 @@
"aidl/android/media/AudioPortRole.aidl",
"aidl/android/media/AudioPortType.aidl",
"aidl/android/media/AudioProfileSys.aidl",
+ "aidl/android/media/AudioRoute.aidl",
"aidl/android/media/AudioTimestampInternal.aidl",
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioVibratorInfo.aidl",
+ "aidl/android/media/DeviceConnectedState.aidl",
"aidl/android/media/EffectDescriptor.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
+ "aidl/android/media/SurroundSoundConfig.aidl",
],
imports: [
"android.media.audio.common.types-V2",
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 620cdc2..4384f97 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -810,10 +810,10 @@
}
status_t AudioFlingerClientAdapter::setDeviceConnectedState(
- const struct audio_port_v7 *port, bool connected) {
+ const struct audio_port_v7 *port, media::DeviceConnectedState state) {
media::AudioPortFw aidlPort = VALUE_OR_RETURN_STATUS(
legacy2aidl_audio_port_v7_AudioPortFw(*port));
- return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
+ return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, state));
}
status_t AudioFlingerClientAdapter::setSimulateDeviceConnections(bool enabled) {
@@ -1369,9 +1369,9 @@
}
Status AudioFlingerServerAdapter::setDeviceConnectedState(
- const media::AudioPortFw& port, bool connected) {
+ const media::AudioPortFw& port, media::DeviceConnectedState state) {
audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPortFw_audio_port_v7(port));
- return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
+ return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, state));
}
Status AudioFlingerServerAdapter::setSimulateDeviceConnections(bool enabled) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index f0b4d11..7c0ce57 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1306,6 +1306,7 @@
streamType = AUDIO_STREAM_DTMF;
}
attr = AudioSystem::streamTypeToAttributes(streamType);
+ attr.flags = AUDIO_FLAG_LOW_LATENCY;
const size_t frameCount = mProcessSize;
status_t status = mpAudioTrack->set(
@@ -1314,7 +1315,7 @@
AUDIO_FORMAT_PCM_16_BIT,
AUDIO_CHANNEL_OUT_MONO,
frameCount,
- AUDIO_OUTPUT_FLAG_FAST,
+ AUDIO_OUTPUT_FLAG_NONE,
wp<AudioTrack::IAudioTrackCallback>::fromExisting(this),
0, // notificationFrames
0, // sharedBuffer
diff --git a/media/libaudioclient/aidl/android/media/AudioRoute.aidl b/media/libaudioclient/aidl/android/media/AudioRoute.aidl
new file mode 100644
index 0000000..5ee2161
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioRoute.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * TODO(b/280077672): This is a temporary copy of the stable
+ * android.hardware.audio.core.AudioRoute. Interfaces from the Core API do not
+ * support the CPP backend. This copy will be removed either by moving the
+ * AudioRoute from core to a.m.a.common or by switching the framework internal
+ * interfaces to the NDK backend.
+ * {@hide}
+ */
+parcelable AudioRoute {
+ /**
+ * The list of IDs of source audio ports ('AudioPort.id').
+ * There must be at least one source in a valid route and all IDs must be
+ * unique.
+ */
+ int[] sourcePortIds;
+ /** The ID of the sink audio port ('AudioPort.id'). */
+ int sinkPortId;
+ /** If set, only one source can be active, mixing is not supported. */
+ boolean isExclusive;
+}
diff --git a/media/libaudioclient/aidl/android/media/DeviceConnectedState.aidl b/media/libaudioclient/aidl/android/media/DeviceConnectedState.aidl
new file mode 100644
index 0000000..e401384
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/DeviceConnectedState.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * {@hide}
+ */
+@Backing(type="int")
+enum DeviceConnectedState {
+ CONNECTED = 0,
+ DISCONNECTED = 1,
+ PREPARE_TO_DISCONNECT = 2,
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 4d9fef4..884cd30 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -27,6 +27,7 @@
import android.media.CreateRecordResponse;
import android.media.CreateTrackRequest;
import android.media.CreateTrackResponse;
+import android.media.DeviceConnectedState;
import android.media.OpenInputRequest;
import android.media.OpenInputResponse;
import android.media.OpenOutputRequest;
@@ -227,7 +228,7 @@
int getAAudioHardwareBurstMinUsec();
- void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
+ void setDeviceConnectedState(in AudioPortFw devicePort, DeviceConnectedState state);
// Used for tests only. Requires AIDL HAL to work.
void setSimulateDeviceConnections(boolean enabled);
diff --git a/media/libaudioclient/aidl/android/media/ISoundDose.aidl b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
index 0e2a5ab..6cb22ef 100644
--- a/media/libaudioclient/aidl/android/media/ISoundDose.aidl
+++ b/media/libaudioclient/aidl/android/media/ISoundDose.aidl
@@ -49,13 +49,11 @@
oneway void updateAttenuation(float attenuationDB, int device);
/**
- * Disable the calculation of sound dose. This has the effect that no MEL
- * values will be computed on the framework side. The MEL returned from
- * the IHalSoundDoseCallbacks will be ignored.
- * Should only be called once at startup if the AudioService does not
- * support CSD.
+ * Enables/disables the calculation of sound dose. This has the effect that
+ * if disabled no MEL values will be computed on the framework side. The MEL
+ * returned from the IHalSoundDoseCallbacks will be ignored.
*/
- oneway void disableCsd();
+ oneway void setCsdEnabled(boolean enabled);
/* -------------------------- Test API methods --------------------------
/** Get the currently used RS2 upper bound. */
diff --git a/media/libaudioclient/aidl/android/media/SurroundSoundConfig.aidl b/media/libaudioclient/aidl/android/media/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..f83fdef
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/SurroundSoundConfig.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.audio.common.AudioFormatDescription;
+
+/**
+ * TODO(b/280077672): This is a temporary copy of the stable
+ * android.hardware.audio.core.SurroundSoundConfig parcelable.
+ * Interfaces from the Core API do not support the CPP backend. This copy will
+ * be removed either by moving the AudioRoute from core to a.m.a.common or by
+ * switching the framework internal interfaces to the NDK backend.
+ * {@hide}
+ */
+parcelable SurroundSoundConfig {
+ parcelable SurroundFormatFamily {
+ /**
+ * A primaryFormat shall get an entry in the Surround Settings dialog on TV
+ * devices. There must be a corresponding Java ENCODING_... constant
+ * defined in AudioFormat.java, and a display name defined in
+ * AudioFormat.toDisplayName.
+ */
+ AudioFormatDescription primaryFormat;
+ /**
+ * List of formats that shall be equivalent to the primaryFormat from the
+ * users' point of view and don't need a dedicated Surround Settings
+ * dialog entry.
+ */
+ AudioFormatDescription[] subFormats;
+ }
+ SurroundFormatFamily[] formatFamilies;
+}
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 1803862..6e28d51 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -361,7 +361,8 @@
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
- virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+ virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+ media::DeviceConnectedState state) = 0;
virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
@@ -481,7 +482,8 @@
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) override;
int32_t getAAudioMixerBurstCount() override;
int32_t getAAudioHardwareBurstMinUsec() override;
- status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override;
+ status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+ media::DeviceConnectedState state) override;
status_t setSimulateDeviceConnections(bool enabled) override;
status_t setRequestedLatencyMode(audio_io_handle_t output,
audio_latency_mode_t mode) override;
@@ -711,7 +713,8 @@
std::vector<media::audio::common::AudioMMapPolicyInfo> *_aidl_return) override;
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
- Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+ Status setDeviceConnectedState(const media::AudioPortFw& port,
+ media::DeviceConnectedState state) override;
Status setSimulateDeviceConnections(bool enabled) override;
Status setRequestedLatencyMode(
int output, media::audio::common::AudioLatencyMode mode) override;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 1dbcb86..3c05b0b 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -74,6 +74,12 @@
cc_library_headers {
name: "libaudiohal_headers",
+ header_libs: [
+ "libeffectsconfig_headers",
+ ],
+
+ export_header_lib_headers: ["libeffectsconfig_headers"],
+
export_include_dirs: ["include"],
}
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 9dbb591..09e70eb 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -35,6 +35,7 @@
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libaudiohal_deathhandler",
+ "libeffectsconfig",
"libhidlbase",
"libhidlmemory",
],
@@ -287,15 +288,17 @@
"android.hardware.common.fmq-V1-ndk",
],
shared_libs: [
- "libbinder_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",
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index aafe6e0..f993907 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -23,10 +23,9 @@
#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
-#include <android/binder_enums.h>
-#include <binder/Enums.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdkCpp.h>
#include <media/AidlConversionUtil.h>
#include <mediautils/TimeCheck.h>
#include <Utils.h>
@@ -96,77 +95,35 @@
portConfig->format = config.base.format;
}
-template<typename OutEnum, typename OutEnumRange, typename InEnum>
-ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
- using InIntType = std::underlying_type_t<InEnum>;
- static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
-
- InIntType inEnumIndex = static_cast<InIntType>(e);
- OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
- if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
- return ::android::base::unexpected(BAD_VALUE);
- }
- return outEnum;
-}
-
-template<typename NdkEnum, typename CppEnum>
-ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
- return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
-}
-
-template<typename CppEnum, typename NdkEnum>
-ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
- return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
-}
-
-ConversionResult<android::media::audio::common::AudioDeviceAddress>
-ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
- using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
- using NdkTag = AudioDeviceAddress::Tag;
-
- CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
-
- switch (cppTag) {
- case CppTag::id:
- return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
- ndk.get<NdkTag::id>());
- case CppTag::mac:
- return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
- ndk.get<NdkTag::mac>());
- case CppTag::ipv4:
- return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
- ndk.get<NdkTag::ipv4>());
- case CppTag::ipv6:
- return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
- ndk.get<NdkTag::ipv6>());
- case CppTag::alsa:
- return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
- ndk.get<NdkTag::alsa>());
- }
-
- return ::android::base::unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
- media::audio::common::AudioDevice cpp;
- cpp.type.type = VALUE_OR_RETURN(
- ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
- cpp.type.connection = ndk.type.connection;
- cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
- return cpp;
-}
-
-ConversionResult<media::audio::common::AudioMMapPolicyInfo>
-ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
- media::audio::common::AudioMMapPolicyInfo cpp;
- cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
- cpp.mmapPolicy = VALUE_OR_RETURN(
- ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
+// Note: these converters are for types defined in different AIDL files. Although these
+// AIDL files are copies of each other, however formally these are different types
+// thus we don't use a conversion via a parcelable.
+ConversionResult<media::AudioRoute> ndk2cpp_AudioRoute(const AudioRoute& ndk) {
+ media::AudioRoute cpp;
+ cpp.sourcePortIds.insert(
+ cpp.sourcePortIds.end(), ndk.sourcePortIds.begin(), ndk.sourcePortIds.end());
+ cpp.sinkPortId = ndk.sinkPortId;
+ cpp.isExclusive = ndk.isExclusive;
return cpp;
}
} // namespace
+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);
+}
+
+status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
+ *routes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::convertContainer<std::vector<media::AudioRoute>>(
+ mRoutes, ndk2cpp_AudioRoute));
+ return OK;
+}
+
status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
@@ -176,8 +133,7 @@
TIME_CHECK();
if (mModule == nullptr) return NO_INIT;
std::vector<AudioPort> ports;
- RETURN_STATUS_IF_ERROR(
- statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
__func__, mInstance.c_str());
std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
@@ -204,6 +160,9 @@
std::transform(portConfigs.begin(), portConfigs.end(),
std::inserter(mPortConfigs, mPortConfigs.end()),
[](const auto& p) { return std::make_pair(p.id, p); });
+ std::transform(mPortConfigs.begin(), mPortConfigs.end(),
+ std::inserter(mInitialPortConfigIds, mInitialPortConfigIds.end()),
+ [](const auto& pcPair) { return pcPair.first; });
std::vector<AudioPatch> patches;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(mModule->getAudioPatches(&patches))); // OK if empty
@@ -357,12 +316,14 @@
this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
+ resetUnusedPatchesAndPortConfigs();
const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
// Find / create AudioPortConfigs for the device port and the mix port,
// then find / create a patch between them, and open a stream on the mix port.
AudioPortConfig devicePortConfig;
bool created = false;
- RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, aidlConfig,
+ &devicePortConfig, &created));
if (created) {
cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
}
@@ -888,8 +849,8 @@
media::audio::common::AudioMMapPolicyType policyType,
std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
TIME_CHECK();
- AudioMMapPolicyType mmapPolicyType =
- VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
+ AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
+ cpp2ndk_AudioMMapPolicyType(policyType));
std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
@@ -966,12 +927,32 @@
return OK;
}
+status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
+ // There is not AIDL API defined for `prepareToDisconnectExternalDevice`.
+ // Call `setConnectedState` instead.
+ // TODO(b/279824103): call prepareToDisconnectExternalDevice when it is added.
+ const status_t status = setConnectedState(port, false /*connected*/);
+ if (status == NO_ERROR) {
+ mDeviceDisconnectionNotified.insert(port->id);
+ }
+ return status;
+}
+
status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
TIME_CHECK();
if (!mModule) return NO_INIT;
if (port == nullptr) {
return BAD_VALUE;
}
+ if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
+ // For device disconnection, APM will first call `prepareToDisconnectExternalDevice`
+ // and then call `setConnectedState`. However, there is no API for
+ // `prepareToDisconnectExternalDevice` yet. In that case, `setConnectedState` will be
+ // called when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if
+ // previous call is successful. Also remove the cache here to avoid a large cache after
+ // a long run.
+ return NO_ERROR;
+ }
bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
::aidl::android::AudioPortDirection::INPUT;
AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
@@ -1109,7 +1090,7 @@
return OK;
}
-status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
+status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device, const AudioConfig* config,
AudioPortConfig* portConfig, bool* created) {
auto portConfigIt = findPortConfig(device);
if (portConfigIt == mPortConfigs.end()) {
@@ -1121,6 +1102,9 @@
}
AudioPortConfig requestedPortConfig;
requestedPortConfig.portId = portsIt->first;
+ if (config != nullptr) {
+ setPortConfigFromConfig(&requestedPortConfig, *config);
+ }
RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(requestedPortConfig, &portConfigIt,
created));
} else {
@@ -1223,7 +1207,8 @@
portConfig, created);
} else if (requestedPortConfig.ext.getTag() == Tag::device) {
return findOrCreatePortConfig(
- requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
+ requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
+ portConfig, created);
}
ALOGW("%s: unsupported audio port config: %s",
__func__, requestedPortConfig.toString().c_str());
@@ -1252,7 +1237,6 @@
[&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
}
-
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
const AudioConfig& config, const AudioIoFlags& flags,
const std::set<int32_t>& destinationPortIds) {
@@ -1265,10 +1249,20 @@
std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
config.base.sampleRate) != prof.sampleRates.end());
};
+ static const std::vector<AudioOutputFlags> kOptionalOutputFlags{AudioOutputFlags::BIT_PERFECT};
+ int optionalFlags = 0;
+ auto flagMatches = [&flags, &optionalFlags](const AudioIoFlags& portFlags) {
+ // Ports should be able to match if the optional flags are not requested.
+ return portFlags == flags ||
+ (portFlags.getTag() == AudioIoFlags::Tag::output &&
+ AudioIoFlags::make<AudioIoFlags::Tag::output>(
+ portFlags.get<AudioIoFlags::Tag::output>() &
+ ~optionalFlags) == flags);
+ };
auto matcher = [&](const auto& pair) {
const auto& p = pair.second;
return p.ext.getTag() == AudioPortExt::Tag::mix &&
- p.flags == flags &&
+ flagMatches(p.flags) &&
(destinationPortIds.empty() ||
std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
[&](const int32_t destId) { return mRoutingMatrix.count(
@@ -1276,7 +1270,24 @@
(p.profiles.empty() ||
std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
p.profiles.end()); };
- return std::find_if(mPorts.begin(), mPorts.end(), matcher);
+ auto result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
+ if (result == mPorts.end() && flags.getTag() == AudioIoFlags::Tag::output) {
+ auto optionalOutputFlagsIt = kOptionalOutputFlags.begin();
+ while (result == mPorts.end() && optionalOutputFlagsIt != kOptionalOutputFlags.end()) {
+ if (isBitPositionFlagSet(
+ flags.get<AudioIoFlags::Tag::output>(), *optionalOutputFlagsIt)) {
+ // If the flag is set by the request, it must be matched.
+ ++optionalOutputFlagsIt;
+ continue;
+ }
+ optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
+ result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
+ ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
+ "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
+ flags.toString().c_str(), mInstance.c_str(), optionalFlags);
+ }
+ }
+ return result;
}
DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
@@ -1358,18 +1369,20 @@
for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
}
+ for (int32_t id : mInitialPortConfigIds) {
+ portConfigIds.erase(id);
+ }
for (int32_t id : portConfigIds) resetPortConfig(id);
}
status_t DeviceHalAidl::updateRoutes() {
TIME_CHECK();
- std::vector<AudioRoute> routes;
RETURN_STATUS_IF_ERROR(
- statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
- ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
+ statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
+ ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
__func__, mInstance.c_str());
mRoutingMatrix.clear();
- for (const auto& r : routes) {
+ for (const auto& r : mRoutes) {
for (auto portId : r.sourcePortIds) {
mRoutingMatrix.emplace(r.sinkPortId, portId);
mRoutingMatrix.emplace(portId, r.sinkPortId);
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index e4d5ec6..f2c64de 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -69,6 +69,10 @@
class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
public CallbackBroker, public MicrophoneInfoProvider {
public:
+ status_t getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) override;
+
+ status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
@@ -161,6 +165,8 @@
status_t getSoundDoseInterface(const std::string& module,
::ndk::SpAIBinder* soundDoseBinder) override;
+ status_t prepareToDisconnectExternalDevice(const struct audio_port_v7 *port) override;
+
status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
status_t setSimulateDeviceConnections(bool enabled) override;
@@ -185,6 +191,7 @@
using PortConfigs = std::map<int32_t /*port config ID*/,
::aidl::android::media::audio::common::AudioPortConfig>;
using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+ using Routes = std::vector<::aidl::android::hardware::audio::core::AudioRoute>;
// Answers the question "whether portID 'first' is reachable from portID 'second'?"
// It's not a map because both portIDs are known. The matrix is symmetric.
using RoutingMatrix = std::set<std::pair<int32_t, int32_t>>;
@@ -215,6 +222,7 @@
::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
status_t findOrCreatePortConfig(
const ::aidl::android::media::audio::common::AudioDevice& device,
+ const ::aidl::android::media::audio::common::AudioConfig* config,
::aidl::android::media::audio::common::AudioPortConfig* portConfig,
bool* created);
status_t findOrCreatePortConfig(
@@ -284,12 +292,15 @@
int32_t mDefaultInputPortId = -1;
int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
+ std::set<int32_t> mInitialPortConfigIds;
Patches mPatches;
+ Routes mRoutes;
RoutingMatrix mRoutingMatrix;
Streams mStreams;
Microphones mMicrophones;
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
+ std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
};
} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index e0b1afb..d67cbdc 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -104,6 +104,15 @@
}
}
+status_t DeviceHalHidl::getAudioPorts(
+ std::vector<media::audio::common::AudioPort> *ports __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t DeviceHalHidl::getAudioRoutes(std::vector<media::AudioRoute> *routes __unused) {
+ return INVALID_OPERATION;
+}
+
status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
// Obsolete.
return INVALID_OPERATION;
@@ -430,6 +439,7 @@
template <typename HalPort>
status_t DeviceHalHidl::getAudioPortImpl(HalPort *port) {
+ using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioPort;
if (mDevice == 0) return NO_INIT;
AudioPort hidlPort;
HidlUtils::audioPortFromHal(*port, &hidlPort);
@@ -472,6 +482,7 @@
}
status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
+ using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioPortConfig;
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
AudioPortConfig hidlConfig;
@@ -535,9 +546,29 @@
}
#endif
+status_t DeviceHalHidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
+ // For HIDL HAL, there is not API to call notify the HAL to prepare for device connected
+ // state changed. Call `setConnectedState` directly.
+ const status_t status = setConnectedState(port, false /*connected*/);
+ if (status == NO_ERROR) {
+ // Cache the port id so that it won't disconnect twice.
+ mDeviceDisconnectionNotified.insert(port->id);
+ }
+ return status;
+}
+
status_t DeviceHalHidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
+ using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::AudioPort;
TIME_CHECK();
if (mDevice == 0) return NO_INIT;
+ if (!connected && mDeviceDisconnectionNotified.erase(port->id) > 0) {
+ // For device disconnection, APM will first call `prepareToDisconnectExternalDevice` and
+ // then call `setConnectedState`. However, in HIDL HAL, there is no API for
+ // `prepareToDisconnectExternalDevice`. In that case, HIDL HAL will call `setConnectedState`
+ // when calling `prepareToDisconnectExternalDevice`. Do not call to the HAL if previous
+ // call is successful. Also remove the cache here to avoid a large cache after a long run.
+ return NO_ERROR;
+ }
#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
if (supportsSetConnectedState7_1) {
AudioPort hidlPort;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index afaad51..7222f03 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -29,6 +29,10 @@
class DeviceHalHidl : public DeviceHalInterface, public CoreConversionHelperHidl
{
public:
+ status_t getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) override;
+
+ status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
status_t getSupportedDevices(uint32_t *devices) override;
@@ -138,6 +142,8 @@
status_t getSoundDoseInterface(const std::string& module,
::ndk::SpAIBinder* soundDoseBinder) override;
+ status_t prepareToDisconnectExternalDevice(const struct audio_port_v7* port) override;
+
private:
friend class DevicesFactoryHalHidl;
sp<::android::hardware::audio::CPP_VERSION::IDevice> mDevice;
@@ -146,6 +152,7 @@
bool supportsSetConnectedState7_1 = true;
class SoundDoseWrapper;
const std::unique_ptr<SoundDoseWrapper> mSoundDoseWrapper;
+ std::set<audio_port_handle_t> mDeviceDisconnectionNotified;
// Can not be constructed directly by clients.
explicit DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device);
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 2eaaf5d..8345cd2 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -14,26 +14,67 @@
* limitations under the License.
*/
+#include <memory>
+
#define LOG_TAG "DevicesFactoryHalAidl"
//#define LOG_NDEBUG 0
#include <aidl/android/hardware/audio/core/IModule.h>
#include <android/binder_manager.h>
#include <binder/IServiceManager.h>
-#include <memory>
+#include <media/AidlConversionNdkCpp.h>
+#include <media/AidlConversionUtil.h>
#include <utils/Log.h>
#include "DeviceHalAidl.h"
#include "DevicesFactoryHalAidl.h"
-using namespace ::aidl::android::hardware::audio::core;
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::core::IConfig;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::SurroundSoundConfig;
+using aidl::android::media::audio::common::AudioHalEngineConfig;
using ::android::detail::AudioHalVersionInfo;
namespace android {
-DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> iconfig)
- : mIConfig(std::move(iconfig)) {
- ALOG_ASSERT(iconfig != nullptr, "Provided default IConfig service is NULL");
+namespace {
+
+ConversionResult<media::SurroundSoundConfig::SurroundFormatFamily>
+ndk2cpp_SurroundSoundConfigFormatFamily(const SurroundSoundConfig::SurroundFormatFamily& ndk) {
+ media::SurroundSoundConfig::SurroundFormatFamily cpp;
+ cpp.primaryFormat = VALUE_OR_RETURN(ndk2cpp_AudioFormatDescription(ndk.primaryFormat));
+ cpp.subFormats = VALUE_OR_RETURN(::aidl::android::convertContainer<std::vector<
+ media::audio::common::AudioFormatDescription>>(ndk.subFormats,
+ ndk2cpp_AudioFormatDescription));
+ return cpp;
+}
+
+ConversionResult<media::SurroundSoundConfig>
+ndk2cpp_SurroundSoundConfig(const SurroundSoundConfig& ndk) {
+ media::SurroundSoundConfig cpp;
+ cpp.formatFamilies = VALUE_OR_RETURN(::aidl::android::convertContainer<std::vector<
+ media::SurroundSoundConfig::SurroundFormatFamily>>(ndk.formatFamilies,
+ ndk2cpp_SurroundSoundConfigFormatFamily));
+ return cpp;
+}
+
+} // namespace
+
+DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> config)
+ : mConfig(std::move(config)) {
+}
+
+status_t DevicesFactoryHalAidl::getDeviceNames(std::vector<std::string> *names) {
+ if (names == nullptr) {
+ return BAD_VALUE;
+ }
+ AServiceManager_forEachDeclaredInstance(IModule::descriptor, static_cast<void*>(names),
+ [](const char* instance, void* context) {
+ if (strcmp(instance, "default") == 0) instance = "primary";
+ static_cast<decltype(names)>(context)->push_back(instance);
+ });
+ return OK;
}
// Opens a device with the specified name. To close the device, it is
@@ -43,19 +84,22 @@
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;
- // FIXME: Normally we will list available HAL modules and connect to them,
- // however currently we still get the list of module names from the config.
- // Since the example service does not have all modules, the SM will wait
- // for the missing ones forever.
- if (strcmp(name, "primary") == 0 || strcmp(name, "r_submix") == 0 || strcmp(name, "usb") == 0) {
+ 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 the service is a nullptr, the device will not be really functional,
+ // If the service is a nullptr, the device object will not be really functional,
// but will not crash either.
*device = sp<DeviceHalAidl>::make(name, service);
return OK;
@@ -97,18 +141,28 @@
AudioHalVersionInfo DevicesFactoryHalAidl::getHalVersion() const {
int32_t versionNumber = 0;
- if (mIConfig != 0) {
- if (ndk::ScopedAStatus status = mIConfig->getInterfaceVersion(&versionNumber);
- !status.isOk()) {
- ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
- }
- } else {
- ALOGW("%s no IConfig instance", __func__);
+ if (ndk::ScopedAStatus status = mConfig->getInterfaceVersion(&versionNumber); !status.isOk()) {
+ ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
}
// AIDL does not have minor version, fill 0 for all versions
return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
}
+status_t DevicesFactoryHalAidl::getSurroundSoundConfig(media::SurroundSoundConfig *config) {
+ SurroundSoundConfig ndkConfig;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mConfig->getSurroundSoundConfig(&ndkConfig)));
+ *config = VALUE_OR_RETURN_STATUS(ndk2cpp_SurroundSoundConfig(ndkConfig));
+ return OK;
+}
+
+status_t DevicesFactoryHalAidl::getEngineConfig(
+ media::audio::common::AudioHalEngineConfig *config) {
+ AudioHalEngineConfig ndkConfig;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mConfig->getEngineConfig(&ndkConfig)));
+ *config = VALUE_OR_RETURN_STATUS(ndk2cpp_AudioHalEngineConfig(ndkConfig));
+ return OK;
+}
+
// 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 cb627bc..21957bc 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -26,7 +26,9 @@
{
public:
explicit DevicesFactoryHalAidl(
- std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> iConfig);
+ std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> config);
+
+ status_t getDeviceNames(std::vector<std::string> *names) override;
// Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object.
@@ -38,8 +40,12 @@
android::detail::AudioHalVersionInfo getHalVersion() const override;
+ status_t getSurroundSoundConfig(media::SurroundSoundConfig *config) override;
+
+ status_t getEngineConfig(media::audio::common::AudioHalEngineConfig *config) override;
+
private:
- const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mIConfig;
+ const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
~DevicesFactoryHalAidl() = default;
};
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 9f06f83..eef60b5 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -106,6 +106,10 @@
}
#endif
+status_t DevicesFactoryHalHidl::getDeviceNames(std::vector<std::string> *names __unused) {
+ return INVALID_OPERATION;
+}
+
status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
auto factories = copyDeviceFactories();
if (factories.empty()) return NO_INIT;
@@ -232,6 +236,16 @@
return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
}
+status_t DevicesFactoryHalHidl::getSurroundSoundConfig(
+ media::SurroundSoundConfig *config __unused) {
+ return INVALID_OPERATION;
+}
+
+status_t DevicesFactoryHalHidl::getEngineConfig(
+ media::audio::common::AudioHalEngineConfig *config __unused) {
+ return INVALID_OPERATION;
+}
+
// Main entry-point to the shared library.
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index 5294728..3285af7 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -37,6 +37,8 @@
explicit DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
void onFirstRef() override;
+ status_t getDeviceNames(std::vector<std::string> *names) override;
+
// Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object.
status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
@@ -47,6 +49,10 @@
android::detail::AudioHalVersionInfo getHalVersion() const override;
+ status_t getSurroundSoundConfig(media::SurroundSoundConfig *config) override;
+
+ status_t getEngineConfig(media::audio::common::AudioHalEngineConfig *config) override;
+
private:
friend class ServiceNotificationListener;
void addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify);
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index bc05aa0..0dcb8ee 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -23,6 +23,7 @@
//#define LOG_NDEBUG 0
#include <error/expected_utils.h>
+#include <aidl/android/media/audio/common/AudioStreamType.h>
#include <android/binder_manager.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionEffect.h>
@@ -35,11 +36,13 @@
#include "EffectsFactoryHalAidl.h"
using ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid;
-using aidl::android::aidl_utils::statusTFromBinderStatus;
-using aidl::android::hardware::audio::effect::Descriptor;
-using aidl::android::hardware::audio::effect::IFactory;
-using aidl::android::media::audio::common::AudioUuid;
-using android::detail::AudioHalVersionInfo;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::Processing;
+using ::aidl::android::media::audio::common::AudioUuid;
+using ::android::base::unexpected;
+using ::android::detail::AudioHalVersionInfo;
namespace android {
namespace effect {
@@ -92,7 +95,8 @@
[](const Descriptor& desc) { return !desc.common.id.proxy.has_value(); });
return list;
}()),
- mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()) {
+ mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
+ mEffectProcessings(nullptr /* TODO: add AIDL implementation */) {
ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
mProxyDescList.size());
@@ -269,6 +273,19 @@
return 0 != mUuidProxyMap.count(uuid);
}
+std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
+ return mEffectProcessings;
+}
+
+::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
+ if (!mEffectProcessings) {
+ return ::android::base::unexpected(BAD_VALUE);
+ }
+
+ // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file
+ return 0;
+}
+
} // namespace effect
// When a shared library is built from a static library, even explicit
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index debfacf..70a7012 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -62,6 +62,10 @@
detail::AudioHalVersionInfo getHalVersion() const override;
+ std::shared_ptr<const effectsConfig::Processings> getProcessings() const override;
+
+ ::android::error::Result<size_t> getSkippedElements() const override;
+
private:
const std::shared_ptr<IFactory> mFactory;
const detail::AudioHalVersionInfo mHalVersion;
@@ -77,6 +81,8 @@
const std::vector<Descriptor> mNonProxyDescList;
// total number of effects including proxy effects
const size_t mEffectCount;
+ // Query result of pre and post processing from effect factory
+ const std::shared_ptr<const effectsConfig::Processings> mEffectProcessings;
std::mutex mLock;
uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 172ebdf..210c4b5 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -33,10 +33,11 @@
#include "android/media/AudioHalVersion.h"
+using ::android::base::unexpected;
using ::android::detail::AudioHalVersionInfo;
+using ::android::hardware::Return;
using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
-using ::android::hardware::Return;
namespace android {
namespace effect {
@@ -78,9 +79,11 @@
}
EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
- : EffectConversionHelperHidl("EffectsFactory"), mCache(new EffectDescriptorCache) {
- ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
- mEffectsFactory = std::move(effectsFactory);
+ : EffectConversionHelperHidl("EffectsFactory"),
+ mEffectsFactory(std::move(effectsFactory)),
+ mCache(new EffectDescriptorCache),
+ mParsingResult(effectsConfig::parse()) {
+ ALOG_ASSERT(mEffectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
}
status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -228,6 +231,17 @@
return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
}
+std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalHidl::getProcessings() const {
+ return mParsingResult.parsedConfig;
+}
+
+::android::error::Result<size_t> EffectsFactoryHalHidl::getSkippedElements() const {
+ if (!mParsingResult.parsedConfig) {
+ return ::android::base::unexpected(BAD_VALUE);
+ }
+ return mParsingResult.nbSkippedElement;
+}
+
} // namespace effect
// When a shared library is built from a static library, even explicit
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 9875154..4110ba3 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -17,6 +17,7 @@
#pragma once
#include <memory>
+#include <vector>
#include PATH(android/hardware/audio/effect/FILE_VERSION/IEffectsFactory.h)
#include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -62,9 +63,19 @@
android::detail::AudioHalVersionInfo getHalVersion() const override;
+ std::shared_ptr<const effectsConfig::Processings> getProcessings() const override;
+
+ ::android::error::Result<size_t> getSkippedElements() const override;
+
private:
- sp<IEffectsFactory> mEffectsFactory;
- std::unique_ptr<EffectDescriptorCache> mCache;
+ const sp<IEffectsFactory> mEffectsFactory;
+ const std::unique_ptr<EffectDescriptorCache> mCache;
+ /**
+ * Configuration file parser result, used by getProcessings() and getConfigParseResult().
+ * This struct holds the result of parsing a configuration file. The result includes the parsed
+ * configuration data, as well as any errors that occurred during parsing.
+ */
+ const effectsConfig::ParsingResult mParsingResult;
};
} // namespace effect
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index e8d8998..45f2922 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -19,6 +19,8 @@
#include <android/media/audio/common/AudioMMapPolicyInfo.h>
#include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioPort.h>
+#include <android/media/AudioRoute.h>
#include <error/Result.h>
#include <media/audiohal/EffectHalInterface.h>
#include <system/audio.h>
@@ -38,6 +40,10 @@
class DeviceHalInterface : public virtual RefBase
{
public:
+ virtual status_t getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) = 0;
+
+ virtual status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) = 0;
+
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
virtual status_t getSupportedDevices(uint32_t *devices) = 0;
@@ -149,6 +155,8 @@
virtual status_t getSoundDoseInterface(const std::string& module,
::ndk::SpAIBinder* soundDoseBinder) = 0;
+ virtual status_t prepareToDisconnectExternalDevice(const struct audio_port_v7* port) = 0;
+
protected:
// Subclasses can not be constructed directly by clients.
DeviceHalInterface() {}
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index be3a723..8397e9b 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -16,6 +16,8 @@
#pragma once
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <android/media/SurroundSoundConfig.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -34,6 +36,8 @@
class DevicesFactoryHalInterface : public RefBase
{
public:
+ virtual status_t getDeviceNames(std::vector<std::string> *names) = 0;
+
// Opens a device with the specified name. To close the device, it is
// necessary to release references to the returned object.
virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device) = 0;
@@ -46,6 +50,10 @@
virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
+ virtual status_t getSurroundSoundConfig(media::SurroundSoundConfig *config) = 0;
+
+ virtual status_t getEngineConfig(media::audio::common::AudioHalEngineConfig *config) = 0;
+
static sp<DevicesFactoryHalInterface> create();
protected:
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index d740fe9..832df18 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -15,8 +15,10 @@
*/
#pragma once
+#include <vector>
#include <media/audiohal/EffectHalInterface.h>
+#include <media/EffectsConfig.h>
#include <system/audio_effect.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -33,21 +35,24 @@
virtual status_t queryNumberEffects(uint32_t *pNumEffects) = 0;
// Returns a descriptor of the next available effect.
- virtual status_t getDescriptor(uint32_t index,
- effect_descriptor_t *pDescriptor) = 0;
+ virtual status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) = 0;
- virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
- effect_descriptor_t *pDescriptor) = 0;
+ virtual status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+ effect_descriptor_t* pDescriptor) = 0;
virtual status_t getDescriptors(const effect_uuid_t *pEffectType,
std::vector<effect_descriptor_t> *descriptors) = 0;
+ virtual std::shared_ptr<const effectsConfig::Processings> getProcessings() const = 0;
+
+ // status_t if parser return error, skipped elements if parsing result is OK (always 0 for AIDL)
+ virtual error::Result<size_t> getSkippedElements() const = 0;
+
// Creates an effect engine of the specified type.
// To release the effect engine, it is necessary to release references
// to the returned effect object.
- virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
- int32_t sessionId, int32_t ioId, int32_t deviceId,
- sp<EffectHalInterface> *effect) = 0;
+ virtual status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+ int32_t deviceId, sp<EffectHalInterface>* effect) = 0;
virtual status_t dumpEffects(int fd) = 0;
diff --git a/media/libaudiousecasevalidation/UsecaseValidator.cpp b/media/libaudiousecasevalidation/UsecaseValidator.cpp
index 0e5a824..d62df3a 100644
--- a/media/libaudiousecasevalidation/UsecaseValidator.cpp
+++ b/media/libaudiousecasevalidation/UsecaseValidator.cpp
@@ -99,10 +99,8 @@
audio_attributes_t attrRet = attributes;
- // Check if attribute usage media or unknown has been set.
- bool isUsageValid = this->isUsageValid(attributes);
-
- if (isUsageValid && m_lookup.isGameStream(streamId)) {
+ if (isUsageValid(attributes.usage) && isContentTypeValid(attributes.content_type)
+ && areFlagsValid(attributes.flags) && m_lookup.isGameStream(streamId)) {
ALOGI("%s update usage: %d to AUDIO_USAGE_GAME for output: %d pid: %d package: %s",
__func__, attributes.usage, streamId, attributionSource.pid,
attributionSource.packageName.value_or("").c_str());
@@ -117,9 +115,9 @@
/**
* Check if attribute usage valid.
*/
- bool isUsageValid(const audio_attributes_t& attr) {
- ALOGV("isUsageValid attr.usage: %d", attr.usage);
- switch (attr.usage) {
+ bool isUsageValid(audio_usage_t usage) {
+ ALOGV("isUsageValid usage: %d", usage);
+ switch (usage) {
case AUDIO_USAGE_MEDIA:
case AUDIO_USAGE_UNKNOWN:
return true;
@@ -129,6 +127,27 @@
return false;
}
+ bool isContentTypeValid(audio_content_type_t contentType) {
+ ALOGV("isContentTypeValid contentType: %d", contentType);
+ switch (contentType) {
+ case AUDIO_CONTENT_TYPE_MUSIC:
+ case AUDIO_CONTENT_TYPE_MOVIE:
+ case AUDIO_CONTENT_TYPE_UNKNOWN:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ bool areFlagsValid(audio_flags_mask_t flags) {
+ ALOGV("areFlagsValid flags: %#x", flags);
+ if ((flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
+ return true;
+ }
+ return false;
+ }
+
protected:
UsecaseLookup m_lookup;
};
diff --git a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp
index d92c8ba..5768a9b 100644
--- a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp
+++ b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.cpp
@@ -52,10 +52,8 @@
*/
error::Result<audio_attributes_t> UsecaseValidatorTest::testStartClient(audio_io_handle_t streamId,
audio_port_handle_t portId,
- audio_usage_t usage) {
+ audio_attributes_t attributes) {
content::AttributionSourceState attributionSource;
- audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
- attributes.usage = usage;
return m_validator->startClient(streamId, portId, attributionSource, attributes, NULL);
}
@@ -141,11 +139,14 @@
mediaPortId = testCreatePortId(mediaStreamId);
EXPECT_NE(mediaPortId, 0);
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.usage = AUDIO_USAGE_GAME;
// Start client on game stream.
- testStartClient(gameStreamId, gamePortId, AUDIO_USAGE_GAME);
+ testStartClient(gameStreamId, gamePortId, attributes);
+ attributes.usage = AUDIO_USAGE_MEDIA;
// Start client on media stream.
- testStartClient(mediaStreamId, mediaPortId, AUDIO_USAGE_MEDIA);
+ testStartClient(mediaStreamId, mediaPortId, attributes);
// Unregister media stream before stopClient.
EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
@@ -175,18 +176,23 @@
voiceCommPortId = testCreatePortId(gameStreamId);
EXPECT_NE(voiceCommPortId, 0);
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
// Verify attributes on game stream.
- auto attr = testStartClient(gameStreamId, gamePortId, AUDIO_USAGE_GAME);
+ attributes.usage = AUDIO_USAGE_GAME;
+ auto attr = testStartClient(gameStreamId, gamePortId, attributes);
EXPECT_EQ(attr.value().usage, AUDIO_USAGE_GAME);
- attr = testStartClient(gameStreamId, voiceCommPortId, AUDIO_USAGE_VOICE_COMMUNICATION);
+ attributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
+ attr = testStartClient(gameStreamId, voiceCommPortId, attributes);
EXPECT_EQ(attr.value().usage, AUDIO_USAGE_VOICE_COMMUNICATION);
// Verify attributes on media stream.
- attr = testStartClient(mediaStreamId, mediaPortId, AUDIO_USAGE_MEDIA);
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attr = testStartClient(mediaStreamId, mediaPortId, attributes);
EXPECT_EQ(attr.value().usage, AUDIO_USAGE_MEDIA);
- attr = testStartClient(mediaStreamId, unknownPortId, AUDIO_USAGE_UNKNOWN);
+ attributes.usage = AUDIO_USAGE_UNKNOWN;
+ attr = testStartClient(mediaStreamId, unknownPortId, attributes);
EXPECT_EQ(attr.value().usage, AUDIO_USAGE_UNKNOWN);
// Stop client on game and media stream.
@@ -215,16 +221,79 @@
unknownPortId = testCreatePortId(gameStreamId);
EXPECT_NE(unknownPortId, 0);
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ attributes.flags = AUDIO_FLAG_LOW_LATENCY;
// Verify attributes on game stream.
- auto attr = testStartClient(gameStreamId, mediaPortId, AUDIO_USAGE_MEDIA);
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ auto attr = testStartClient(gameStreamId, mediaPortId, attributes);
EXPECT_EQ(attr.value().usage, AUDIO_USAGE_GAME);
- attr = testStartClient(gameStreamId, unknownPortId, AUDIO_USAGE_UNKNOWN);
+ attributes.usage = AUDIO_USAGE_UNKNOWN;
+ attr = testStartClient(gameStreamId, unknownPortId, attributes);
EXPECT_EQ(attr.value().usage, AUDIO_USAGE_GAME);
// Unregister game stream.
EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
}
+/**
+ * Verify attributes usage does not change for non low latency clients.
+ */
+TEST_F(UsecaseValidatorTest, testAttributesUsageUnChangedIfNotLowLatency) {
+ audio_io_handle_t gameStreamId;
+ audio_port_handle_t mediaPortId, unknownPortId;
+
+ // Register game and media stream.
+ gameStreamId = testRegisterStream(true);
+ EXPECT_NE(gameStreamId, 0);
+
+ // Assign portId.
+ mediaPortId = testCreatePortId(gameStreamId);
+ EXPECT_NE(mediaPortId, 0);
+ unknownPortId = testCreatePortId(gameStreamId);
+ EXPECT_NE(unknownPortId, 0);
+
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ // Verify attributes on game stream.
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ auto attr = testStartClient(gameStreamId, mediaPortId, attributes);
+ EXPECT_EQ(attr.value().usage, AUDIO_USAGE_MEDIA);
+
+ attributes.usage = AUDIO_USAGE_UNKNOWN;
+ attr = testStartClient(gameStreamId, unknownPortId, attributes);
+ EXPECT_EQ(attr.value().usage, AUDIO_USAGE_UNKNOWN);
+
+ // Unregister game stream.
+ EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
+}
+
+/**
+ * Verify attributes usage does not change for content type speech.
+ */
+TEST_F(UsecaseValidatorTest, testAttributesUsageUnChangedIfSpeech) {
+ audio_io_handle_t gameStreamId;
+ audio_port_handle_t mediaPortId, unknownPortId;
+
+ // Register game and media stream.
+ gameStreamId = testRegisterStream(true);
+ EXPECT_NE(gameStreamId, 0);
+
+ // Assign portId.
+ mediaPortId = testCreatePortId(gameStreamId);
+ EXPECT_NE(mediaPortId, 0);
+ unknownPortId = testCreatePortId(gameStreamId);
+ EXPECT_NE(unknownPortId, 0);
+
+ audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+ // Verify attributes on game stream.
+ attributes.usage = AUDIO_USAGE_MEDIA;
+ attributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
+ auto attr = testStartClient(gameStreamId, mediaPortId, attributes);
+ EXPECT_EQ(attr.value().usage, AUDIO_USAGE_MEDIA);
+
+ // Unregister game stream.
+ EXPECT_EQ(m_validator->unregisterStream(gameStreamId), 0);
+}
+
} // namespace media
} // namespace android
diff --git a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h
index 3159ab4..8cbd0f0 100644
--- a/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h
+++ b/media/libaudiousecasevalidation/tests/UsecaseValidator-test.h
@@ -69,7 +69,7 @@
audio_port_handle_t testCreatePortId(audio_io_handle_t streamId);
error::Result<audio_attributes_t> testStartClient(audio_io_handle_t streamId,
audio_port_handle_t portId,
- audio_usage_t usage);
+ audio_attributes_t attributes);
error::Result<audio_attributes_t> testVerifyAudioAttributes(audio_io_handle_t streamId,
audio_usage_t usage);
diff --git a/media/libeffects/config/Android.bp b/media/libeffects/config/Android.bp
index b02dcb6..293a9c2 100644
--- a/media/libeffects/config/Android.bp
+++ b/media/libeffects/config/Android.bp
@@ -27,8 +27,21 @@
"libcutils",
],
- header_libs: ["libaudio_system_headers"],
- export_header_lib_headers: ["libaudio_system_headers"],
+ header_libs: [
+ "libaudio_system_headers",
+ "liberror_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libaudio_system_headers",
+ "liberror_headers",
+ ],
+
+ export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+ name: "libeffectsconfig_headers",
export_include_dirs: ["include"],
}
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index 57d4dd7..a9730e5 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -22,8 +22,10 @@
* @see audio_effects_conf_V2_0.xsd for documentation on each structure
*/
+#include <error/Result.h>
#include <system/audio_effect.h>
+#include <cstddef>
#include <map>
#include <memory>
#include <string>
@@ -75,6 +77,12 @@
std::string address;
};
+struct Processings {
+ std::vector<InputStream> preprocess;
+ std::vector<OutputStream> postprocess;
+ std::vector<DeviceEffects> deviceprocess;
+};
+
/** Parsed configuration.
* Intended to be a transient structure only used for deserialization.
* Note: Everything is copied in the configuration from the xml dom.
@@ -82,19 +90,16 @@
* consider keeping a private handle on the xml dom and replace all strings by dom pointers.
* Or even better, use SAX parsing to avoid the allocations all together.
*/
-struct Config {
+struct Config : public Processings {
float version;
Libraries libraries;
Effects effects;
- std::vector<OutputStream> postprocess;
- std::vector<InputStream> preprocess;
- std::vector<DeviceEffects> deviceprocess;
};
/** Result of `parse(const char*)` */
struct ParsingResult {
/** Parsed config, nullptr if the xml lib could not load the file */
- std::unique_ptr<Config> parsedConfig;
+ std::shared_ptr<const Config> parsedConfig;
size_t nbSkippedElement; //< Number of skipped invalid library, effect or processing chain
const std::string configPath; //< Path to the loaded configuration
};
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 1696233..3096659 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -286,7 +286,7 @@
return {nullptr, 0, std::move(path)};
}
- auto config = std::make_unique<Config>();
+ auto config = std::make_shared<Config>();
size_t nbSkippedElements = 0;
auto registerFailure = [&nbSkippedElements](bool result) {
nbSkippedElements += result ? 0 : 1;
diff --git a/media/libeffects/factory/Android.bp b/media/libeffects/factory/Android.bp
index 22838a3..d94093e 100644
--- a/media/libeffects/factory/Android.bp
+++ b/media/libeffects/factory/Android.bp
@@ -39,6 +39,7 @@
header_libs: [
"libaudioeffects",
"libeffects_headers",
+ "liberror_headers",
],
export_header_lib_headers: ["libeffects_headers"],
}
@@ -56,7 +57,6 @@
"-Werror",
],
-
shared_libs: [
"libeffectsconfig",
"libeffects",
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index b3371a3..3bc889c 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -85,9 +85,7 @@
static const std::string kEqualizerEffectName = "EqualizerBundle";
static const Descriptor kEqualizerDesc = {
.common = {.id = {.type = getEffectTypeUuidEqualizer(),
- .uuid = getEffectImplUuidEqualizerBundle(),
- .proxy = getEffectImplUuidEqualizerProxy()},
-
+ .uuid = getEffectImplUuidEqualizerBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
@@ -102,8 +100,7 @@
static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
static const Descriptor kBassBoostDesc = {
.common = {.id = {.type = getEffectTypeUuidBassBoost(),
- .uuid = getEffectImplUuidBassBoostBundle(),
- .proxy = getEffectImplUuidBassBoostProxy()},
+ .uuid = getEffectImplUuidBassBoostBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL,
@@ -121,8 +118,7 @@
static const Descriptor kVirtualizerDesc = {
.common = {.id = {.type = getEffectTypeUuidVirtualizer(),
- .uuid = getEffectImplUuidVirtualizerBundle(),
- .proxy = getEffectImplUuidVirtualizerProxy()},
+ .uuid = getEffectImplUuidVirtualizerBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::LAST,
.volume = Flags::Volume::CTRL,
@@ -139,8 +135,7 @@
static const std::string kVolumeEffectName = "Volume";
static const Descriptor kVolumeDesc = {
.common = {.id = {.type = getEffectTypeUuidVolume(),
- .uuid = getEffectImplUuidVolumeBundle(),
- .proxy = std::nullopt},
+ .uuid = getEffectImplUuidVolumeBundle()},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::LAST,
.volume = Flags::Volume::CTRL},
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index c2c605d..f69307b 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -485,14 +485,17 @@
return mAAudioHwBurstMinMicros;
}
-status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) {
+status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port,
+ media::DeviceConnectedState state) {
status_t final_result = NO_INIT;
Mutex::Autolock _l(mLock);
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_CONNECTED_STATE;
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
- status_t result = dev->setConnectedState(port, connected);
+ status_t result = state == media::DeviceConnectedState::PREPARE_TO_DISCONNECT
+ ? dev->prepareToDisconnectExternalDevice(port)
+ : dev->setConnectedState(port, state == media::DeviceConnectedState::CONNECTED);
// Same logic as with setParameter: it's a success if at least one
// HAL module accepts the update.
if (final_result != NO_ERROR) {
@@ -1236,21 +1239,20 @@
output.portId = portId;
if (lStatus == NO_ERROR) {
+ // no risk of deadlock because AudioFlinger::mLock is held
+ Mutex::Autolock _dl(thread->mLock);
// Connect secondary outputs. Failure on a secondary output must not imped the primary
// Any secondary output setup failure will lead to a desync between the AP and AF until
// the track is destroyed.
updateSecondaryOutputsForTrack_l(track.get(), thread, secondaryOutputs);
- }
-
- // move effect chain to this output thread if an effect on same session was waiting
- // for a track to be created
- if (lStatus == NO_ERROR && effectThread != NULL) {
- // no risk of deadlock because AudioFlinger::mLock is held
- Mutex::Autolock _dl(thread->mLock);
- Mutex::Autolock _sl(effectThread->mLock);
- if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
- effectThreadId = thread->id();
- effectIds = thread->getEffectIds_l(sessionId);
+ // move effect chain to this output thread if an effect on same session was waiting
+ // for a track to be created
+ if (effectThread != nullptr) {
+ Mutex::Autolock _sl(effectThread->mLock);
+ if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+ effectThreadId = thread->id();
+ effectIds = thread->getEffectIds_l(sessionId);
+ }
}
}
@@ -3952,7 +3954,7 @@
patchTrack->setPeerProxy(patchRecord, true /* holdReference */);
patchRecord->setPeerProxy(patchTrack, false /* holdReference */);
}
- track->setTeePatches(std::move(teePatches));
+ track->setTeePatchesToUpdate(std::move(teePatches));
}
sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 323ce0e..47fa74f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -297,7 +297,8 @@
virtual int32_t getAAudioHardwareBurstMinUsec();
- virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected);
+ virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+ media::DeviceConnectedState state);
virtual status_t setSimulateDeviceConnections(bool enabled);
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 5a3bcdc..e024319 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -81,7 +81,7 @@
}
bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
- if (mSoundDoseManager->isCsdDisabled()) {
+ if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return false;
}
@@ -107,7 +107,7 @@
void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
const std::vector<playback_track_metadata_v7_t>& metadataVec) {
- if (mSoundDoseManager->isCsdDisabled()) {
+ if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
}
@@ -143,7 +143,7 @@
void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
const PatchPanel::Patch& patch) {
- if (mSoundDoseManager->isCsdDisabled()) {
+ if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
}
@@ -207,7 +207,7 @@
}
void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
- if (mSoundDoseManager->isCsdDisabled()) {
+ if (!mSoundDoseManager->isCsdEnabled()) {
ALOGV("%s csd is disabled", __func__);
return;
}
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index ad191b0..0e1a3c9 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -186,7 +186,9 @@
}
sp<os::ExternalVibration> getExternalVibration() const { return mExternalVibration; }
- void setTeePatches(TeePatches teePatches);
+ // This function should be called with holding thread lock.
+ void updateTeePatches();
+ void setTeePatchesToUpdate(TeePatches teePatchesToUpdate);
void tallyUnderrunFrames(size_t frames) override {
if (isOut()) { // we expect this from output tracks only
@@ -369,6 +371,7 @@
bool mPauseHwPending = false; // direct/offload track request for thread pause
audio_output_flags_t mFlags;
TeePatches mTeePatches;
+ std::optional<TeePatches> mTeePatchesToUpdate;
const float mSpeed;
const bool mIsSpatialized;
const bool mIsBitPerfect;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fbd1395..8d0c648 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4104,6 +4104,10 @@
setHalLatencyMode_l();
+ for (const auto &track : mActiveTracks ) {
+ track->updateTeePatches();
+ }
+
// signal actual start of output stream when the render position reported by the kernel
// starts moving.
if (!mStandby && !mHalStarted && mKernelPositionOnStandby !=
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6b5ddce..7d2c4db 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1491,15 +1491,24 @@
*backInserter++ = metadata;
}
-void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
- mTeePatches = std::move(teePatches);
- if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
- mState == TrackBase::STOPPING_1) {
- forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+void AudioFlinger::PlaybackThread::Track::updateTeePatches() {
+ if (mTeePatchesToUpdate.has_value()) {
+ forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
+ mTeePatches = mTeePatchesToUpdate.value();
+ if (mState == TrackBase::ACTIVE || mState == TrackBase::RESUMING ||
+ mState == TrackBase::STOPPING_1) {
+ forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+ }
+ mTeePatchesToUpdate.reset();
}
}
+void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
+ ALOGW_IF(mTeePatchesToUpdate.has_value(),
+ "%s, existing tee patches to update will be ignored", __func__);
+ mTeePatchesToUpdate = std::move(teePatchesToUpdate);
+}
+
// must be called with player thread lock held
void AudioFlinger::PlaybackThread::Track::processMuteEvent_l(const sp<
IAudioManager>& audioManager, mute_state_t muteState)
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index f94ab1e..a114a38 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -50,7 +50,7 @@
size_t channelCount, audio_format_t format) {
std::lock_guard _l(mLock);
- if (mHalSoundDose != nullptr && !mDisableCsd) {
+ if (mHalSoundDose != nullptr && mEnabledCsd) {
ALOGD("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
return nullptr;
}
@@ -290,11 +290,11 @@
return binder::Status::ok();
}
-binder::Status SoundDoseManager::SoundDose::disableCsd() {
+binder::Status SoundDoseManager::SoundDose::setCsdEnabled(bool enabled) {
ALOGV("%s", __func__);
auto soundDoseManager = mSoundDoseManager.promote();
if (soundDoseManager != nullptr) {
- soundDoseManager->disableCsd();
+ soundDoseManager->setCsdEnabled(enabled);
}
return binder::Status::ok();
}
@@ -365,26 +365,27 @@
}
}
-void SoundDoseManager::disableCsd() {
+void SoundDoseManager::setCsdEnabled(bool enabled) {
ALOGV("%s", __func__);
std::lock_guard _l(mLock);
- mDisableCsd = true;
+ mEnabledCsd = enabled;
- // Normally, there should be no active MelProcessors when this method is called
- // We pause however every cached MelProcessor as a defensive mechanism to not
- // have unnecessary processing
for (auto& activeEntry : mActiveProcessors) {
auto melProcessor = activeEntry.second.promote();
if (melProcessor != nullptr) {
- melProcessor->pause();
+ if (enabled) {
+ melProcessor->resume();
+ } else {
+ melProcessor->pause();
+ }
}
}
}
-bool SoundDoseManager::isCsdDisabled() {
+bool SoundDoseManager::isCsdEnabled() {
std::lock_guard _l(mLock);
- return mDisableCsd;
+ return mEnabledCsd;
}
void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
@@ -411,7 +412,7 @@
}
bool SoundDoseManager::isSoundDoseHalSupported() const {
- if (mDisableCsd) {
+ if (!mEnabledCsd) {
return false;
}
@@ -455,7 +456,7 @@
float currentCsd;
{
std::lock_guard _l(mLock);
- if (mDisableCsd) {
+ if (!mEnabledCsd) {
return;
}
@@ -496,7 +497,7 @@
{
std::lock_guard _l(mLock);
- if (mDisableCsd) {
+ if (!mEnabledCsd) {
return;
}
}
@@ -522,7 +523,7 @@
std::string output;
{
std::lock_guard _l(mLock);
- if (mDisableCsd) {
+ 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 5081ce4..6c02afb 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -101,8 +101,8 @@
/** Clear all map entries with passed audio_port_handle_t. */
void clearMapDeviceIdEntries(audio_port_handle_t deviceId);
- /** Returns true if CSD is disabled. */
- bool isCsdDisabled();
+ /** Returns true if CSD is enabled. */
+ bool isCsdEnabled();
std::string dump() const;
@@ -137,7 +137,7 @@
const std::vector<media::SoundDoseRecord>& records) override;
binder::Status updateAttenuation(float attenuationDB, int device) override;
binder::Status getOutputRs2UpperBound(float* value) override;
- binder::Status disableCsd() override;
+ binder::Status setCsdEnabled(bool enabled) override;
binder::Status getCsd(float* value) override;
binder::Status forceUseFrameworkMel(bool useFrameworkMel) override;
@@ -170,7 +170,7 @@
sp<media::ISoundDoseCallback> getSoundDoseCallback() const;
void updateAttenuation(float attenuationDB, audio_devices_t deviceType);
- void disableCsd();
+ void setCsdEnabled(bool enabled);
void setUseFrameworkMel(bool useFrameworkMel);
void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
bool isSoundDoseHalSupported() const;
@@ -202,7 +202,7 @@
bool mUseFrameworkMel GUARDED_BY(mLock) = true;
bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
- bool mDisableCsd GUARDED_BY(mLock) = false;
+ bool mEnabledCsd GUARDED_BY(mLock) = true;
};
} // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 3d1cf76..134d068 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_AUDIOPOLICY_INTERFACE_H
#define ANDROID_AUDIOPOLICY_INTERFACE_H
+#include <android/media/DeviceConnectedState.h>
#include <media/AudioCommonTypes.h>
#include <media/AudioContainers.h>
#include <media/AudioDeviceTypeAddr.h>
@@ -567,7 +568,8 @@
virtual status_t updateSecondaryOutputs(
const TrackSecondaryOutputsMap& trackSecondaryOutputs) = 0;
- virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+ virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+ media::DeviceConnectedState state) = 0;
virtual status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) = 0;
};
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 56a692b..b678662 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -116,14 +116,13 @@
}
void AudioPolicyManager::broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
- audio_policy_dev_state_t state)
+ media::DeviceConnectedState state)
{
audio_port_v7 devicePort;
device->toAudioPort(&devicePort);
- if (status_t status = mpClientInterface->setDeviceConnectedState(
- &devicePort, state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+ if (status_t status = mpClientInterface->setDeviceConnectedState(&devicePort, state);
status != OK) {
- ALOGE("Error %d while setting connected state for device %s", status,
+ ALOGE("Error %d while setting connected state for device %s", state,
device->getDeviceTypeAddr().toString(false).c_str());
}
}
@@ -206,14 +205,14 @@
// Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic
// parameters on newly connected devices (instead of opening the outputs...)
- broadcastDeviceConnectionState(device, state);
+ broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED);
if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
mAvailableOutputDevices.remove(device);
mHwModules.cleanUpForDevice(device);
- broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+ broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
return INVALID_OPERATION;
}
@@ -235,8 +234,9 @@
ALOGV("%s() disconnecting output device %s", __func__, device->toString().c_str());
- // Send Disconnect to HALs
- broadcastDeviceConnectionState(device, state);
+ // Notify the HAL to prepare to disconnect device
+ broadcastDeviceConnectionState(
+ device, media::DeviceConnectedState::PREPARE_TO_DISCONNECT);
// remove device from available output devices
mAvailableOutputDevices.remove(device);
@@ -245,6 +245,9 @@
checkOutputsForDevice(device, state, outputs);
+ // Send Disconnect to HALs
+ broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
+
// Reset active device codec
device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
@@ -384,12 +387,12 @@
// Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
// parameters on newly connected devices (instead of opening the inputs...)
- broadcastDeviceConnectionState(device, state);
+ broadcastDeviceConnectionState(device, media::DeviceConnectedState::CONNECTED);
if (checkInputsForDevice(device, state) != NO_ERROR) {
mAvailableInputDevices.remove(device);
- broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
+ broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
mHwModules.cleanUpForDevice(device);
@@ -407,13 +410,17 @@
ALOGV("%s() disconnecting input device %s", __func__, device->toString().c_str());
- // Set Disconnect to HALs
- broadcastDeviceConnectionState(device, state);
+ // Notify the HAL to prepare to disconnect device
+ broadcastDeviceConnectionState(
+ device, media::DeviceConnectedState::PREPARE_TO_DISCONNECT);
mAvailableInputDevices.remove(device);
checkInputsForDevice(device, state);
+ // Set Disconnect to HALs
+ broadcastDeviceConnectionState(device, media::DeviceConnectedState::DISCONNECTED);
+
// remove device from mReportedFormatsMap cache
mReportedFormatsMap.erase(device);
} break;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 2924ee1..dc82d54 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -35,6 +35,7 @@
#include <media/PatchBuilder.h>
#include "AudioPolicyInterface.h"
+#include <android/media/DeviceConnectedState.h>
#include <android/media/audio/common/AudioPort.h>
#include <AudioPolicyManagerObserver.h>
#include <AudioPolicyConfig.h>
@@ -1060,13 +1061,16 @@
void updateAudioProfiles(const sp<DeviceDescriptor>& devDesc, audio_io_handle_t ioHandle,
AudioProfileVector &profiles);
+ // Notify the policy client to prepare for disconnecting external device.
+ void prepareToDisconnectExternalDevice(const sp<DeviceDescriptor> &device);
+
// Notify the policy client of any change of device state with AUDIO_IO_HANDLE_NONE,
// so that the client interprets it as global to audio hardware interfaces.
// It can give a chance to HAL implementer to retrieve dynamic capabilities associated
// to this device for example.
// TODO avoid opening stream to retrieve capabilities of a profile.
void broadcastDeviceConnectionState(const sp<DeviceDescriptor> &device,
- audio_policy_dev_state_t state);
+ media::DeviceConnectedState state);
// updates device caching and output for streams that can influence the
// routing of notifications
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 1bb89df..887f210 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -309,13 +309,13 @@
}
status_t AudioPolicyService::AudioPolicyClient::setDeviceConnectedState(
- const struct audio_port_v7 *port, bool connected) {
+ const struct audio_port_v7 *port, media::DeviceConnectedState state) {
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
if (af == nullptr) {
ALOGW("%s: could not get AudioFlinger", __func__);
return PERMISSION_DENIED;
}
- return af->setDeviceConnectedState(port, connected);
+ return af->setDeviceConnectedState(port, state);
}
status_t AudioPolicyService::AudioPolicyClient::invalidateTracks(
@@ -328,5 +328,4 @@
return af->invalidateTracks(portIds);
}
-
} // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index c7a60c2..b111865 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -41,26 +41,25 @@
// AudioPolicyEffects Implementation
// ----------------------------------------------------------------------------
-AudioPolicyEffects::AudioPolicyEffects()
-{
- status_t loadResult = loadAudioEffectXmlConfig();
+AudioPolicyEffects::AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
+ // load xml config with effectsFactoryHal
+ status_t loadResult = loadAudioEffectConfig(effectsFactoryHal);
if (loadResult == NO_ERROR) {
- mDefaultDeviceEffectFuture = std::async(
- std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
+ mDefaultDeviceEffectFuture =
+ std::async(std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
} else if (loadResult < 0) {
- ALOGW("Failed to load XML effect configuration, fallback to .conf");
+ ALOGW("Failed to query effect configuration, fallback to load .conf");
// load automatic audio effect modules
if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
- loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+ loadAudioEffectConfigLegacy(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
} else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
- loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+ loadAudioEffectConfigLegacy(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
}
} else if (loadResult > 0) {
ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
}
}
-
AudioPolicyEffects::~AudioPolicyEffects()
{
size_t i = 0;
@@ -907,10 +906,18 @@
return NO_ERROR;
}
-status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
- auto result = effectsConfig::parse();
- if (result.parsedConfig == nullptr) {
- return -ENOENT;
+status_t AudioPolicyEffects::loadAudioEffectConfig(
+ const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
+ if (!effectsFactoryHal) {
+ ALOGE("%s Null EffectsFactoryHalInterface", __func__);
+ return UNEXPECTED_NULL;
+ }
+
+ const auto skippedElements = VALUE_OR_RETURN_STATUS(effectsFactoryHal->getSkippedElements());
+ const auto processings = effectsFactoryHal->getProcessings();
+ if (!processings) {
+ ALOGE("%s Null processings with %zu skipped elements", __func__, skippedElements);
+ return UNEXPECTED_NULL;
}
auto loadProcessingChain = [](auto& processingChain, auto& streams) {
@@ -924,9 +931,8 @@
}
};
- auto loadDeviceProcessingChain = [](auto &processingChain, auto& devicesEffects) {
+ auto loadDeviceProcessingChain = [](auto& processingChain, auto& devicesEffects) {
for (auto& deviceProcess : processingChain) {
-
auto effectDescs = std::make_unique<EffectDescVector>();
for (auto& effect : deviceProcess.effects) {
effectDescs->mEffects.add(
@@ -938,17 +944,18 @@
}
};
- loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
- loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
+ loadProcessingChain(processings->preprocess, mInputSources);
+ loadProcessingChain(processings->postprocess, mOutputStreams);
+
{
Mutex::Autolock _l(mLock);
- loadDeviceProcessingChain(result.parsedConfig->deviceprocess, mDeviceEffects);
+ loadDeviceProcessingChain(processings->deviceprocess, mDeviceEffects);
}
- // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
- return result.nbSkippedElement;
+
+ return skippedElements;
}
-status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
+status_t AudioPolicyEffects::loadAudioEffectConfigLegacy(const char *path)
{
cnode *root;
char *data;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 13d5d0c..9f65a96 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -20,22 +20,33 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <future>
+
+#include <android-base/thread_annotations.h>
#include <cutils/misc.h>
#include <media/AudioEffect.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <system/audio.h>
#include <utils/Vector.h>
#include <utils/SortedVector.h>
-#include <android-base/thread_annotations.h>
-
-#include <future>
namespace android {
// ----------------------------------------------------------------------------
-// AudioPolicyEffects class
-// This class will manage all effects attached to input and output streams in
-// AudioPolicyService as configured in audio_effects.conf.
+/**
+ * AudioPolicyEffects class.
+ *
+ * This class manages all effects attached to input and output streams in AudioPolicyService.
+ * The effect configurations can be queried in several ways:
+ *
+ * With HIDL HAL, the configuration file `audio_effects.xml` will be loaded by libAudioHal. If this
+ * file does not exist, AudioPolicyEffects class will fallback to load configuration from
+ * `/vendor/etc/audio_effects.conf` (AUDIO_EFFECT_VENDOR_CONFIG_FILE). If this file also does not
+ * exist, the configuration will be loaded from the file `/system/etc/audio_effects.conf`.
+ *
+ * With AIDL HAL, the configuration will be queried with the method `IFactory::queryProcessing()`.
+ */
class AudioPolicyEffects : public RefBase
{
@@ -44,7 +55,7 @@
// The constructor will parse audio_effects.conf
// First it will look whether vendor specific file exists,
// otherwise it will parse the system default file.
- AudioPolicyEffects();
+ explicit AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
virtual ~AudioPolicyEffects();
// NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
@@ -218,7 +229,6 @@
};
-
static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
static audio_source_t inputSourceNameToEnum(const char *name);
@@ -226,8 +236,8 @@
audio_stream_type_t streamNameToEnum(const char *name);
// Parse audio_effects.conf
- status_t loadAudioEffectConfig(const char *path); // TODO: add legacy in the name
- status_t loadAudioEffectXmlConfig(); // TODO: remove "Xml" in the name
+ status_t loadAudioEffectConfigLegacy(const char *path);
+ status_t loadAudioEffectConfig(const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
// Load all effects descriptors in configuration file
status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index af7be52..0d12060 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -476,14 +476,14 @@
}
ALOGV("startOutput()");
sp<AudioPlaybackClient> client;
- sp<AudioPolicyEffects>audioPolicyEffects;
+ sp<AudioPolicyEffects> audioPolicyEffects;
getPlaybackClientAndEffects(portId, client, audioPolicyEffects, __func__);
if (audioPolicyEffects != 0) {
// create audio processors according to stream
- status_t status = audioPolicyEffects->addOutputSessionEffects(
- client->io, client->stream, client->session);
+ status_t status = audioPolicyEffects->addOutputSessionEffects(client->io, client->stream,
+ client->session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGW("Failed to add effects on session %d", client->session);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 974ae38..e5b1c91 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -259,7 +259,8 @@
}
// load audio processing modules
- sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
+ const sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
+ sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects(effectsFactoryHal);
sp<UidPolicy> uidPolicy = new UidPolicy(this);
sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
{
@@ -278,7 +279,7 @@
AudioDeviceTypeAddrVector devices;
bool hasSpatializer = mAudioPolicyManager->canBeSpatialized(&attr, nullptr, devices);
if (hasSpatializer) {
- mSpatializer = Spatializer::create(this);
+ mSpatializer = Spatializer::create(this, effectsFactoryHal);
}
if (mSpatializer == nullptr) {
// No spatializer created, signal the reason: NO_INIT a failure, OK means intended.
@@ -1694,7 +1695,7 @@
}
}
-void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused) {
+void AudioPolicyService::UidPolicy::onUidProcAdjChanged(uid_t uid __unused, int32_t adj __unused) {
}
void AudioPolicyService::UidPolicy::updateOverrideUid(uid_t uid, bool active, bool insert) {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 59aabac..981951a 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -484,7 +484,7 @@
void onUidIdle(uid_t uid, bool disabled) override;
void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
int32_t capability) override;
- void onUidProcAdjChanged(uid_t uid) override;
+ void onUidProcAdjChanged(uid_t uid, int32_t adj) override;
void addOverrideUid(uid_t uid, bool active) { updateOverrideUid(uid, active, true); }
void removeOverrideUid(uid_t uid) { updateOverrideUid(uid, false, false); }
@@ -847,7 +847,7 @@
const TrackSecondaryOutputsMap& trackSecondaryOutputs) override;
status_t setDeviceConnectedState(
- const struct audio_port_v7 *port, bool connected) override;
+ const struct audio_port_v7 *port, media::DeviceConnectedState state) override;
status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
diff --git a/services/audiopolicy/service/Spatializer.cpp b/services/audiopolicy/service/Spatializer.cpp
index 95b8e7c..ee2e0eb 100644
--- a/services/audiopolicy/service/Spatializer.cpp
+++ b/services/audiopolicy/service/Spatializer.cpp
@@ -30,7 +30,6 @@
#include <audio_utils/fixedfft.h>
#include <cutils/bitops.h>
#include <hardware/sensors.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/MediaMetricsItem.h>
@@ -215,18 +214,17 @@
};
// ---------------------------------------------------------------------------
-sp<Spatializer> Spatializer::create(SpatializerPolicyCallback *callback) {
+sp<Spatializer> Spatializer::create(SpatializerPolicyCallback* callback,
+ const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
sp<Spatializer> spatializer;
- sp<EffectsFactoryHalInterface> effectsFactoryHal = EffectsFactoryHalInterface::create();
if (effectsFactoryHal == nullptr) {
ALOGW("%s failed to create effect factory interface", __func__);
return spatializer;
}
std::vector<effect_descriptor_t> descriptors;
- status_t status =
- effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
+ status_t status = effectsFactoryHal->getDescriptors(FX_IID_SPATIALIZER, &descriptors);
if (status != NO_ERROR) {
ALOGW("%s failed to get spatializer descriptor, error %d", __func__, status);
return spatializer;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 23de0c0..0d4d3f6 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -27,6 +27,7 @@
#include <audio_utils/SimpleLog.h>
#include <math.h>
#include <media/AudioEffect.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <media/VectorRecorder.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -95,7 +96,8 @@
private SpatializerPoseController::Listener,
public virtual AudioSystem::SupportedLatencyModesCallback {
public:
- static sp<Spatializer> create(SpatializerPolicyCallback *callback);
+ static sp<Spatializer> create(SpatializerPolicyCallback* callback,
+ const sp<EffectsFactoryHalInterface>& effectsFactoryHal);
~Spatializer() override;
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index 6eca7cc..3629c16 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -103,10 +103,11 @@
++mAudioPortListUpdateCount;
}
- status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override {
- if (connected) {
+ status_t setDeviceConnectedState(const struct audio_port_v7 *port,
+ media::DeviceConnectedState state) override {
+ if (state == media::DeviceConnectedState::CONNECTED) {
mConnectedDevicePorts.push_back(*port);
- } else {
+ } else if (state == media::DeviceConnectedState::DISCONNECTED){
mDisconnectedDevicePorts.push_back(*port);
}
return NO_ERROR;
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 0c04e35..71e34e3 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -96,8 +96,8 @@
const TrackSecondaryOutputsMap& trackSecondaryOutputs __unused) override {
return NO_INIT;
}
- status_t setDeviceConnectedState(
- const struct audio_port_v7 *port __unused, bool connected __unused) override {
+ status_t setDeviceConnectedState(const struct audio_port_v7 *port __unused,
+ media::DeviceConnectedState state __unused) override {
return NO_INIT;
}
status_t invalidateTracks(const std::vector<audio_port_handle_t>& /*portIds*/) override {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a2aafdf..cecced4 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2602,6 +2602,19 @@
}
}
+void CameraService::notifyMonitoredUids(const std::unordered_set<uid_t> ¬ifyUidSet) {
+ Mutex::Autolock lock(mStatusListenerLock);
+
+ for (const auto& it : mListenerList) {
+ if (notifyUidSet.find(it->getListenerUid()) != notifyUidSet.end()) {
+ ALOGV("%s: notifying uid %d", __FUNCTION__, it->getListenerUid());
+ auto ret = it->getListener()->onCameraAccessPrioritiesChanged();
+ it->handleBinderStatus(ret, "%s: Failed to trigger permission callback for %d:%d: %d",
+ __FUNCTION__, it->getListenerUid(), it->getListenerPid(), ret.exceptionCode());
+ }
+ }
+}
+
Status CameraService::notifyDeviceStateChange(int64_t newState) {
const int pid = CameraThreadState::getCallingPid();
const int selfPid = getpid();
@@ -2823,7 +2836,7 @@
// permissions the listener process has / whether it is a vendor listener. Since it might be
// eligible to listen to other camera ids.
mListenerList.emplace_back(serviceListener);
- mUidPolicy->registerMonitorUid(clientUid);
+ mUidPolicy->registerMonitorUid(clientUid, /*openCamera*/false);
}
/* Collect current devices and status */
@@ -2891,7 +2904,7 @@
Mutex::Autolock lock(mStatusListenerLock);
for (auto it = mListenerList.begin(); it != mListenerList.end(); it++) {
if (IInterface::asBinder((*it)->getListener()) == IInterface::asBinder(listener)) {
- mUidPolicy->unregisterMonitorUid((*it)->getListenerUid());
+ mUidPolicy->unregisterMonitorUid((*it)->getListenerUid(), /*closeCamera*/false);
IInterface::asBinder(listener)->unlinkToDeath(*it);
mListenerList.erase(it);
return Status::ok();
@@ -3680,7 +3693,7 @@
// Transition device availability listeners from PRESENT -> NOT_AVAILABLE
sCameraService->updateStatus(StatusInternal::NOT_AVAILABLE, mCameraIdStr);
- sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
+ sCameraService->mUidPolicy->registerMonitorUid(mClientUid, /*openCamera*/true);
// Notify listeners of camera open/close status
sCameraService->updateOpenCloseStatus(mCameraIdStr, true/*open*/, mClientPackageName);
@@ -3788,7 +3801,7 @@
}
mOpsCallback.clear();
- sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
+ sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid, /*closeCamera*/true);
// Notify listeners of camera open/close status
sCameraService->updateOpenCloseStatus(mCameraIdStr, false/*open*/, mClientPackageName);
@@ -3988,24 +4001,51 @@
}
}
-void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid) {
- bool procAdjChange = false;
+/**
+ * When the OOM adj of the uid owning the camera changes, a different uid waiting on camera
+ * privileges may take precedence if the owner's new OOM adj is greater than the waiting package.
+ * Here, we track which monitoredUid has the camera, and track its adj relative to other
+ * monitoredUids. If it is revised above some other monitoredUid, signal
+ * onCameraAccessPrioritiesChanged. This only needs to capture the case where there are two
+ * foreground apps in split screen - state changes will capture all other cases.
+ */
+void CameraService::UidPolicy::onUidProcAdjChanged(uid_t uid, int32_t adj) {
+ std::unordered_set<uid_t> notifyUidSet;
{
Mutex::Autolock _l(mUidLock);
- if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
- procAdjChange = true;
+ auto it = mMonitoredUids.find(uid);
+
+ if (it != mMonitoredUids.end()) {
+ if (it->second.hasCamera) {
+ for (auto &monitoredUid : mMonitoredUids) {
+ if (monitoredUid.first != uid && adj > monitoredUid.second.procAdj) {
+ notifyUidSet.emplace(monitoredUid.first);
+ }
+ }
+ notifyUidSet.emplace(uid);
+ } else {
+ for (auto &monitoredUid : mMonitoredUids) {
+ if (monitoredUid.second.hasCamera && adj < monitoredUid.second.procAdj) {
+ notifyUidSet.emplace(uid);
+ }
+ }
+ }
+ it->second.procAdj = adj;
}
}
- if (procAdjChange) {
+ if (notifyUidSet.size() > 0) {
sp<CameraService> service = mService.promote();
if (service != nullptr) {
- service->notifyMonitoredUids();
+ service->notifyMonitoredUids(notifyUidSet);
}
}
}
-void CameraService::UidPolicy::registerMonitorUid(uid_t uid) {
+/**
+ * Register a uid for monitoring, and note whether it owns a camera.
+ */
+void CameraService::UidPolicy::registerMonitorUid(uid_t uid, bool openCamera) {
Mutex::Autolock _l(mUidLock);
auto it = mMonitoredUids.find(uid);
if (it != mMonitoredUids.end()) {
@@ -4013,18 +4053,28 @@
} else {
MonitoredUid monitoredUid;
monitoredUid.procState = ActivityManager::PROCESS_STATE_NONEXISTENT;
+ monitoredUid.procAdj = resource_policy::UNKNOWN_ADJ;
monitoredUid.refCount = 1;
- mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid));
+ it = mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid)).first;
+ }
+
+ if (openCamera) {
+ it->second.hasCamera = true;
}
}
-void CameraService::UidPolicy::unregisterMonitorUid(uid_t uid) {
+/**
+ * Unregister a uid for monitoring, and note whether it lost ownership of a camera.
+ */
+void CameraService::UidPolicy::unregisterMonitorUid(uid_t uid, bool closeCamera) {
Mutex::Autolock _l(mUidLock);
auto it = mMonitoredUids.find(uid);
if (it != mMonitoredUids.end()) {
it->second.refCount--;
if (it->second.refCount == 0) {
mMonitoredUids.erase(it);
+ } else if (closeCamera) {
+ it->second.hasCamera = false;
}
} else {
ALOGE("%s: Trying to unregister uid: %d which is not monitored!", __FUNCTION__, uid);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ecec15f..8c57d26 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -233,6 +233,7 @@
// Monitored UIDs availability notification
void notifyMonitoredUids();
+ void notifyMonitoredUids(const std::unordered_set<uid_t> ¬ifyUidSet);
// Stores current open session device info in temp file.
void cacheDump();
@@ -763,13 +764,13 @@
void onUidIdle(uid_t uid, bool disabled) override;
void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
int32_t capability) override;
- void onUidProcAdjChanged(uid_t uid) override;
+ void onUidProcAdjChanged(uid_t uid, int adj) override;
void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
void removeOverrideUid(uid_t uid, String16 callingPackage);
- void registerMonitorUid(uid_t uid);
- void unregisterMonitorUid(uid_t uid);
+ void registerMonitorUid(uid_t uid, bool openCamera);
+ void unregisterMonitorUid(uid_t uid, bool closeCamera);
// Implementation of IServiceManager::LocalRegistrationCallback
virtual void onServiceRegistration(const String16& name,
@@ -784,6 +785,8 @@
struct MonitoredUid {
int32_t procState;
+ int32_t procAdj;
+ bool hasCamera;
size_t refCount;
};
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 66077c5..86a0ebc 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -264,7 +264,7 @@
mOpsActive = true;
// Transition device state to OPEN
- sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
+ sCameraService->mUidPolicy->registerMonitorUid(mClientUid, /*openCamera*/true);
return OK;
}
@@ -288,7 +288,7 @@
}
mOpsCallback.clear();
- sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
+ sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid, /*closeCamera*/true);
return OK;
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index b7c86c6..77abeeb 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -2526,6 +2526,10 @@
(mDeviceStateOrientationMap.find(newState) != mDeviceStateOrientationMap.end())) {
mCameraCharacteristics.update(ANDROID_SENSOR_ORIENTATION,
&mDeviceStateOrientationMap[newState], 1);
+ if (mCameraCharNoPCOverride.get() != nullptr) {
+ mCameraCharNoPCOverride->update(ANDROID_SENSOR_ORIENTATION,
+ &mDeviceStateOrientationMap[newState], 1);
+ }
}
}
diff --git a/services/mediaresourcemanager/UidObserver.cpp b/services/mediaresourcemanager/UidObserver.cpp
index f321ebc..4bcd325 100644
--- a/services/mediaresourcemanager/UidObserver.cpp
+++ b/services/mediaresourcemanager/UidObserver.cpp
@@ -170,7 +170,7 @@
int32_t /*capability*/) {
}
-void UidObserver::onUidProcAdjChanged(uid_t /*uid*/) {
+void UidObserver::onUidProcAdjChanged(uid_t /*uid*/, int32_t /*adj*/) {
}
void UidObserver::binderDied(const wp<IBinder>& /*who*/) {
diff --git a/services/mediaresourcemanager/UidObserver.h b/services/mediaresourcemanager/UidObserver.h
index ed76839..b5cc3b9 100644
--- a/services/mediaresourcemanager/UidObserver.h
+++ b/services/mediaresourcemanager/UidObserver.h
@@ -74,7 +74,7 @@
void onUidIdle(uid_t uid, bool disabled) override;
void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
int32_t capability) override;
- void onUidProcAdjChanged(uid_t uid) override;
+ void onUidProcAdjChanged(uid_t uid, int32_t adj) override;
// IServiceManager::LocalRegistrationCallback implementation.
void onServiceRegistration(const String16& name,
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 2b94dbf..e7d14a0 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -196,11 +196,11 @@
: AUDIO_SOURCE_DEFAULT;
audio_flags_mask_t flags;
if (direction == AAUDIO_DIRECTION_OUTPUT) {
- flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
- | AAudioConvert_allowCapturePolicyToAudioFlagsMask(
+ flags = AAudio_computeAudioFlagsMask(
params->getAllowedCapturePolicy(),
params->getSpatializationBehavior(),
- params->isContentSpatialized()));
+ params->isContentSpatialized(),
+ AUDIO_OUTPUT_FLAG_FAST);
} else {
flags = static_cast<audio_flags_mask_t>(AUDIO_FLAG_LOW_LATENCY
| AAudioConvert_privacySensitiveToAudioFlagsMask(params->isPrivacySensitive()));