Merge "Camera: Add support for cropped RAW streams"
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index afbd60e..42e4717 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -53,6 +53,7 @@
using media::audio::common::AudioDeviceAddress;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
using media::audio::common::AudioEncapsulationMetadataType;
using media::audio::common::AudioEncapsulationMode;
using media::audio::common::AudioEncapsulationType;
@@ -63,9 +64,11 @@
using media::audio::common::AudioGainMode;
using media::audio::common::AudioInputFlags;
using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
using media::audio::common::AudioMode;
using media::audio::common::AudioOffloadInfo;
using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
using media::audio::common::AudioPortDeviceExt;
using media::audio::common::AudioPortExt;
using media::audio::common::AudioPortMixExt;
@@ -2131,6 +2134,139 @@
return unexpected(BAD_VALUE);
}
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+ switch (aidl) {
+ case AudioDualMonoMode::OFF:
+ return AUDIO_DUAL_MONO_MODE_OFF;
+ case AudioDualMonoMode::LR:
+ return AUDIO_DUAL_MONO_MODE_LR;
+ case AudioDualMonoMode::LL:
+ return AUDIO_DUAL_MONO_MODE_LL;
+ case AudioDualMonoMode::RR:
+ return AUDIO_DUAL_MONO_MODE_RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_DUAL_MONO_MODE_OFF:
+ return AudioDualMonoMode::OFF;
+ case AUDIO_DUAL_MONO_MODE_LR:
+ return AudioDualMonoMode::LR;
+ case AUDIO_DUAL_MONO_MODE_LL:
+ return AudioDualMonoMode::LL;
+ case AUDIO_DUAL_MONO_MODE_RR:
+ return AudioDualMonoMode::RR;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ AudioPlaybackRate::TimestretchFallbackMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+ return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+ case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+ return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+ case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+ return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+ case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+ return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+ case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+ return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+ case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+ return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+ case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+ return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ AudioPlaybackRate::TimestretchMode aidl) {
+ switch (aidl) {
+ case AudioPlaybackRate::TimestretchMode::DEFAULT:
+ return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+ case AudioPlaybackRate::TimestretchMode::VOICE:
+ return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+ return AudioPlaybackRate::TimestretchMode::DEFAULT;
+ case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+ return AudioPlaybackRate::TimestretchMode::VOICE;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+ audio_playback_rate_t legacy;
+ legacy.mSpeed = aidl.speed;
+ legacy.mPitch = aidl.pitch;
+ legacy.mFallbackMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ aidl.fallbackMode));
+ legacy.mStretchMode = VALUE_OR_RETURN(
+ aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+ return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+ AudioPlaybackRate aidl;
+ aidl.speed = legacy.mSpeed;
+ aidl.pitch = legacy.mPitch;
+ aidl.fallbackMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ legacy.mFallbackMode));
+ aidl.timestretchMode = VALUE_OR_RETURN(
+ legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+ return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+ switch (aidl) {
+ case AudioLatencyMode::FREE:
+ return AUDIO_LATENCY_MODE_FREE;
+ case AudioLatencyMode::LOW:
+ return AUDIO_LATENCY_MODE_LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+ switch (legacy) {
+ case AUDIO_LATENCY_MODE_FREE:
+ return AudioLatencyMode::FREE;
+ case AUDIO_LATENCY_MODE_LOW:
+ return AudioLatencyMode::LOW;
+ }
+ return unexpected(BAD_VALUE);
+}
+
} // namespace android
#if defined(BACKEND_NDK)
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
index e1efff9..c25ddb1 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -35,6 +35,7 @@
#include PREFIX(android/media/audio/common/AudioConfigBase.h)
#include PREFIX(android/media/audio/common/AudioContentType.h)
#include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
@@ -44,11 +45,13 @@
#include PREFIX(android/media/audio/common/AudioGainMode.h)
#include PREFIX(android/media/audio/common/AudioInputFlags.h)
#include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
#include PREFIX(android/media/audio/common/AudioMode.h)
#include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
#include PREFIX(android/media/audio/common/AudioOutputFlags.h)
#include PREFIX(android/media/audio/common/AudioPortExt.h)
#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
#include PREFIX(android/media/audio/common/AudioProfile.h)
#include PREFIX(android/media/audio/common/AudioSource.h)
#include PREFIX(android/media/audio/common/AudioStandard.h)
@@ -287,8 +290,38 @@
ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
const audio_uuid_t& legacy);
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+ audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+ media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+ audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+ const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
} // namespace android
#if defined(BACKEND_NDK)
} // aidl
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 5ea4926..68a8590 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -1091,80 +1091,6 @@
return convertReinterpret<int32_t>(legacy);
}
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
- switch (aidl) {
- case media::AudioDualMonoMode::OFF:
- return AUDIO_DUAL_MONO_MODE_OFF;
- case media::AudioDualMonoMode::LR:
- return AUDIO_DUAL_MONO_MODE_LR;
- case media::AudioDualMonoMode::LL:
- return AUDIO_DUAL_MONO_MODE_LL;
- case media::AudioDualMonoMode::RR:
- return AUDIO_DUAL_MONO_MODE_RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
- switch (legacy) {
- case AUDIO_DUAL_MONO_MODE_OFF:
- return media::AudioDualMonoMode::OFF;
- case AUDIO_DUAL_MONO_MODE_LR:
- return media::AudioDualMonoMode::LR;
- case AUDIO_DUAL_MONO_MODE_LL:
- return media::AudioDualMonoMode::LL;
- case AUDIO_DUAL_MONO_MODE_RR:
- return media::AudioDualMonoMode::RR;
- }
- return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
- return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
- return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
- audio_playback_rate_t legacy;
- legacy.mSpeed = aidl.speed;
- legacy.mPitch = aidl.pitch;
- legacy.mFallbackMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
- legacy.mStretchMode = VALUE_OR_RETURN(
- aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
- return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
- media::AudioPlaybackRate aidl;
- aidl.speed = legacy.mSpeed;
- aidl.pitch = legacy.mPitch;
- aidl.fallbackMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
- aidl.stretchMode = VALUE_OR_RETURN(
- legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
- return aidl;
-}
-
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
const media::TrackSecondaryOutputInfo& aidl) {
@@ -1237,25 +1163,4 @@
indexToEnum_bitmask<audio_direct_mode_t>,
enumToMask_index<int32_t, media::AudioDirectMode>);
}
-
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
- switch (aidl) {
- case media::LatencyMode::FREE:
- return AUDIO_LATENCY_MODE_FREE;
- case media::LatencyMode::LOW:
- return AUDIO_LATENCY_MODE_LOW;
- }
- return unexpected(BAD_VALUE);
-}
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
- switch (legacy) {
- case AUDIO_LATENCY_MODE_FREE:
- return media::LatencyMode::FREE;
- case AUDIO_LATENCY_MODE_LOW:
- return media::LatencyMode::LOW;
- }
- return unexpected(BAD_VALUE);
-}
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 4679731..9ddae1e 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -281,14 +281,12 @@
"aidl/android/media/AudioAttributesInternal.aidl",
"aidl/android/media/AudioClient.aidl",
"aidl/android/media/AudioDirectMode.aidl",
- "aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioFlag.aidl",
"aidl/android/media/AudioGainSys.aidl",
"aidl/android/media/AudioHalVersion.aidl",
"aidl/android/media/AudioIoConfigEvent.aidl",
"aidl/android/media/AudioIoDescriptor.aidl",
"aidl/android/media/AudioPatchFw.aidl",
- "aidl/android/media/AudioPlaybackRate.aidl",
"aidl/android/media/AudioPortFw.aidl",
"aidl/android/media/AudioPortSys.aidl",
"aidl/android/media/AudioPortConfigFw.aidl",
@@ -303,7 +301,6 @@
"aidl/android/media/AudioUniqueIdUse.aidl",
"aidl/android/media/AudioVibratorInfo.aidl",
"aidl/android/media/EffectDescriptor.aidl",
- "aidl/android/media/LatencyMode.aidl",
"aidl/android/media/TrackSecondaryOutputInfo.aidl",
],
imports: [
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 5a1dc64..ad03711 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -672,12 +672,12 @@
}
Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) {
+ int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(
- latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+ latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
std::vector<sp<SupportedLatencyModesCallback>> callbacks;
{
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 22bd2a3..9386b9b 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1266,7 +1266,7 @@
status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
{
AutoMutex lock(mLock);
- media::AudioDualMonoMode mediaMode;
+ media::audio::common::AudioDualMonoMode mediaMode;
const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
if (status == NO_ERROR) {
*mode = VALUE_OR_RETURN_STATUS(
@@ -1381,7 +1381,7 @@
{
AutoMutex lock(mLock);
if (isOffloadedOrDirect_l()) {
- media::AudioPlaybackRate playbackRateTemp;
+ media::audio::common::AudioPlaybackRate playbackRateTemp;
const status_t status = statusTFromBinderStatus(
mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index d895f80..30ccefe 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -822,8 +822,8 @@
status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- media::LatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
- legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+ media::audio::common::AudioLatencyMode modeAidl = VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
}
@@ -834,14 +834,14 @@
}
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl;
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
*modes = VALUE_OR_RETURN_STATUS(
convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
- aidl2legacy_LatencyMode_audio_latency_mode_t));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
return NO_ERROR;
}
@@ -1377,17 +1377,17 @@
}
Status AudioFlingerServerAdapter::setRequestedLatencyMode(
- int32_t output, media::LatencyMode modeAidl) {
+ int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
- aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+ aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
outputLegacy, modeLegacy));
}
Status AudioFlingerServerAdapter::getSupportedLatencyModes(
- int output, std::vector<media::LatencyMode>* _aidl_return) {
+ int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
aidl2legacy_int32_t_audio_io_handle_t(output));
std::vector<audio_latency_mode_t> modesLegacy;
@@ -1395,8 +1395,8 @@
RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
*_aidl_return = VALUE_OR_RETURN_BINDER(
- convertContainer<std::vector<media::LatencyMode>>(
- modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
return Status::ok();
}
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
- OFF = 0,
- LR = 1,
- LL = 2,
- RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- * As this is used for native wire serialization, no need to define
- * audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- * until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
- /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float speed;
- /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
- float pitch;
- /** Interpreted as audio_timestretch_stretch_mode_t */
- int stretchMode;
- /** Interpreted as audio_timestretch_fallback_mode_t */
- int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
import android.media.AudioIoConfigEvent;
import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
/**
* A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
/**
* Called when the latency modes supported on a given output stream change.
* output is the I/O handle of the output stream for which the change is signalled.
- * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+ * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
*/
- oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+ oneway void onSupportedLatencyModesChanged(
+ int output, in AudioLatencyMode[] latencyModes);
}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 7deb384..69810c0 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -37,12 +37,12 @@
import android.media.IAudioTrack;
import android.media.ISoundDose;
import android.media.ISoundDoseCallback;
-import android.media.LatencyMode;
import android.media.MicrophoneInfoData;
import android.media.RenderPosition;
import android.media.TrackSecondaryOutputInfo;
import android.media.audio.common.AudioChannelLayout;
import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
import android.media.audio.common.AudioMMapPolicyInfo;
import android.media.audio.common.AudioMMapPolicyType;
import android.media.audio.common.AudioMode;
@@ -230,21 +230,21 @@
void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
/**
- * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+ * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
* This can be used when some use case on a given mixer/stream can only be enabled
* if a specific latency mode is selected on the audio path below the HAL.
* For instance spatial audio with head tracking.
* output is the I/O handle of the output stream for which the request is made.
* latencyMode is the requested latency mode.
*/
- void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+ void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
/**
* Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
* output is the I/O handle of the output stream to which the query applies.
* returns the list of supported latency modes.
*/
- LatencyMode[] getSupportedLatencyModes(int output);
+ AudioLatencyMode[] getSupportedLatencyModes(int output);
/**
* Requests if the implementation supports controlling the latency modes
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
package android.media;
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
import android.media.AudioTimestampInternal;
import android.media.SharedFileRegion;
import android.media.VolumeShaperConfiguration;
import android.media.VolumeShaperOperation;
import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
/**
* Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
- /** No specific constraint on the latency */
- FREE = 0,
- /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
- LOW = 1,
-}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index ff3598f..a1012a1 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,18 +24,15 @@
#include <android/media/AudioAttributesInternal.h>
#include <android/media/AudioClient.h>
#include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioFlag.h>
#include <android/media/AudioIoConfigEvent.h>
#include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
#include <android/media/AudioPortFw.h>
#include <android/media/AudioPortConfigFw.h>
#include <android/media/AudioPortDeviceExtSys.h>
#include <android/media/AudioTimestampInternal.h>
#include <android/media/AudioUniqueIdUse.h>
#include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
#include <android/media/TrackSecondaryOutputInfo.h>
#include <android/media/SharedFileRegion.h>
@@ -184,26 +181,6 @@
ConversionResult<int32_t>
legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
ConversionResult<TrackSecondaryOutputInfoPair>
aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -220,9 +197,4 @@
ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
-
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 5ed8219..fedf511 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -778,7 +778,8 @@
const media::AudioIoDescriptor& ioDesc) override;
binder::Status onSupportedLatencyModesChanged(
- int output, const std::vector<media::LatencyMode>& latencyModes) override;
+ int output,
+ const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index fdf3113..6b6c407 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -709,9 +709,10 @@
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
- Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+ Status setRequestedLatencyMode(
+ int output, media::audio::common::AudioLatencyMode mode) override;
Status getSupportedLatencyModes(int output,
- std::vector<media::LatencyMode>* _aidl_return) override;
+ std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
Status setBluetoothVariableLatencyEnabled(bool enabled) override;
Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
Status supportsBluetoothVariableLatency(bool* support) override;
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 41d4e16..4b6d5f2 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -24,6 +24,7 @@
defaults: [
"latest_android_media_audio_common_types_cpp_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
],
srcs: [
@@ -76,6 +77,7 @@
"libutils",
"liblog",
"libbinder",
+ "libbinder_ndk",
"libaudioclient",
"libaudiomanager",
"libmedialogservice",
@@ -105,11 +107,11 @@
"libaudiohal_headers",
"libaudioutils_headers",
"libmedia_headers",
- "libsounddose_headers",
],
export_shared_lib_headers: [
"libpermission",
+ "android.hardware.audio.sounddose-V1-ndk",
],
cflags: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d3453f5..d930fb5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2220,9 +2220,9 @@
void AudioFlinger::onSupportedLatencyModesChanged(
audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
- std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
- convertContainer<std::vector<media::LatencyMode>>(modes,
- legacy2aidl_audio_latency_mode_t_LatencyMode));
+ std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+ convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+ modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
Mutex::Autolock _l(mClientLock);
size_t size = mNotificationClients.size();
@@ -2573,6 +2573,9 @@
ALOGE("loadHwModule() error %d loading module %s", rc, name);
return AUDIO_MODULE_HANDLE_NONE;
}
+ if (!mMelReporter->activateHalSoundDoseComputation(name)) {
+ ALOGW("loadHwModule() sound dose reporting is not available");
+ }
mHardwareStatus = AUDIO_HW_INIT;
rc = dev->initCheck();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6dd1cda..173f0c9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <limits.h>
+#include <aidl/android/hardware/audio/sounddose/ISoundDoseFactory.h>
#include <android/media/BnAudioTrack.h>
#include <android/media/IAudioFlingerClient.h>
#include <android/media/IAudioTrackCallback.h>
@@ -701,14 +702,16 @@
binder::Status getVolumeShaperState(
int32_t id,
std::optional<media::VolumeShaperState>* _aidl_return) override;
- binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
- binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+ binder::Status getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return) override;
+ binder::Status setDualMonoMode(
+ media::audio::common::AudioDualMonoMode mode) override;
binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
binder::Status setAudioDescriptionMixLevel(float leveldB) override;
binder::Status getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return) override;
+ media::audio::common::AudioPlaybackRate* _aidl_return) override;
binder::Status setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate) override;
+ const media::audio::common::AudioPlaybackRate& playbackRate) override;
private:
const sp<PlaybackThread::Track> mTrack;
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index b2e8027..b185959 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -22,12 +22,85 @@
#include <android/media/ISoundDoseCallback.h>
#include <audio_utils/power.h>
+#include <android/binder_manager.h>
#include <utils/Log.h>
+using aidl::android::hardware::audio::core::ISoundDose;
+using aidl::android::hardware::audio::sounddose::ISoundDoseFactory;
+
namespace android {
+constexpr std::string_view kSoundDoseInterfaceModule = "/default";
+
+bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module) {
+ if (mSoundDoseManager->forceUseFrameworkMel()) {
+ ALOGD("%s: Forcing use of internal MEL computation.", __func__);
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ if (mSoundDoseFactory == nullptr) {
+ ALOGW("%s: sound dose HAL reporting not available", __func__);
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ std::shared_ptr<ISoundDose> soundDoseInterface;
+ auto result = mSoundDoseFactory->getSoundDose(module, &soundDoseInterface);
+ if (!result.isOk()) {
+ ALOGW("%s: HAL cannot provide sound dose interface for module %s",
+ __func__, module.c_str());
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ if (!mSoundDoseManager->setHalSoundDoseInterface(soundDoseInterface)) {
+ ALOGW("%s: cannot activate HAL MEL reporting for module %s", __func__, module.c_str());
+ activateInternalSoundDoseComputation();
+ return false;
+ }
+
+ std::lock_guard _l(mLock);
+ mUseHalSoundDoseInterface = true;
+ stopInternalMelComputation();
+ return true;
+}
+
+void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+ {
+ std::lock_guard _l(mLock);
+ if (!mUseHalSoundDoseInterface) {
+ // no need to start internal MEL on active patches
+ return;
+ }
+ mUseHalSoundDoseInterface = false;
+ }
+
+ mSoundDoseManager->setHalSoundDoseInterface(nullptr);
+
+ for (const auto& activePatches : mActiveMelPatches) {
+ for (const auto& deviceId : activePatches.second.deviceHandles) {
+ startMelComputationForNewPatch(activePatches.second.streamHandle, deviceId);
+ }
+ }
+}
+
+void AudioFlinger::MelReporter::onFirstRef() {
+ mAudioFlinger.mPatchCommandThread->addListener(this);
+
+ std::string interface =
+ std::string(ISoundDoseFactory::descriptor) + kSoundDoseInterfaceModule.data();
+ AIBinder* binder = AServiceManager_checkService(interface.c_str());
+ if (binder == nullptr) {
+ ALOGW("%s service %s doesn't exist", __func__, interface.c_str());
+ return;
+ }
+
+ mSoundDoseFactory = ISoundDoseFactory::fromBinder(ndk::SpAIBinder(binder));
+}
+
bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
- if (mSoundDoseManager.computeCsdOnAllDevices()) {
+ if (mSoundDoseManager->forceComputeCsdOnAllDevices()) {
return true;
}
@@ -65,17 +138,17 @@
&& shouldComputeMelForDeviceType(patch.mAudioPatch.sinks[i].ext.device.type)) {
audio_port_handle_t deviceId = patch.mAudioPatch.sinks[i].id;
newPatch.deviceHandles.push_back(deviceId);
+ AudioDeviceTypeAddr adt{patch.mAudioPatch.sinks[i].ext.device.type,
+ patch.mAudioPatch.sinks[i].ext.device.address};
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
- // Start the MEL calculation in the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
- if (thread != nullptr) {
- thread->startMelComputation(mSoundDoseManager.getOrCreateProcessorForDevice(
- deviceId,
- newPatch.streamHandle,
- thread->mSampleRate,
- thread->mChannelCount,
- thread->mFormat));
+ bool useHalSoundDoseInterface = !mSoundDoseManager->forceUseFrameworkMel();
+ {
+ std::lock_guard _l(mLock);
+ useHalSoundDoseInterface &= mUseHalSoundDoseInterface;
+ }
+ if (!useHalSoundDoseInterface) {
+ startMelComputationForNewPatch(streamHandle, deviceId);
}
}
}
@@ -84,6 +157,21 @@
mActiveMelPatches[patch.mAudioPatch.id] = newPatch;
}
+void AudioFlinger::MelReporter::startMelComputationForNewPatch(
+ audio_io_handle_t streamHandle, audio_port_handle_t deviceId) {
+ // Start the MEL calculation in the PlaybackThread
+ std::lock_guard _lAf(mAudioFlinger.mLock);
+ auto thread = mAudioFlinger.checkPlaybackThread_l(streamHandle);
+ if (thread != nullptr) {
+ thread->startMelComputation(mSoundDoseManager->getOrCreateProcessorForDevice(
+ deviceId,
+ streamHandle,
+ thread->mSampleRate,
+ thread->mChannelCount,
+ thread->mFormat));
+ }
+}
+
void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
ALOGV("%s", __func__);
@@ -103,25 +191,47 @@
mActiveMelPatches.erase(patchIt);
}
- // Stop MEL calculation for the PlaybackThread
- std::lock_guard _lAf(mAudioFlinger.mLock);
- mSoundDoseManager.removeStreamProcessor(melPatch.streamHandle);
- auto thread = mAudioFlinger.checkPlaybackThread_l(melPatch.streamHandle);
- if (thread != nullptr) {
- thread->stopMelComputation();
+ for (const auto& deviceId : melPatch.deviceHandles) {
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
}
+ stopInternalMelComputationForStream(melPatch.streamHandle);
}
sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
const sp<media::ISoundDoseCallback>& callback) {
// no need to lock since getSoundDoseInterface is synchronized
- return mSoundDoseManager.getSoundDoseInterface(callback);
+ return mSoundDoseManager->getSoundDoseInterface(callback);
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputation() {
+ ALOGV("%s", __func__);
+ std::unordered_map<audio_patch_handle_t, ActiveMelPatch> activePatchesCopy;
+ {
+ std::lock_guard _l(mLock);
+ activePatchesCopy = mActiveMelPatches;
+ mActiveMelPatches.clear();
+ }
+
+ for (const auto& activePatch : activePatchesCopy) {
+ stopInternalMelComputationForStream(activePatch.second.streamHandle);
+ }
+}
+
+void AudioFlinger::MelReporter::stopInternalMelComputationForStream(audio_io_handle_t streamId) {
+ ALOGV("%s: stop internal mel for stream id: %d", __func__, streamId);
+
+ std::lock_guard _lAf(mAudioFlinger.mLock);
+ mSoundDoseManager->removeStreamProcessor(streamId);
+ auto thread = mAudioFlinger.checkPlaybackThread_l(streamId);
+ if (thread != nullptr) {
+ thread->stopMelComputation();
+ }
}
std::string AudioFlinger::MelReporter::dump() {
std::lock_guard _l(mLock);
std::string output("\nSound Dose:\n");
- output.append(mSoundDoseManager.dump());
+ output.append(mSoundDoseManager->dump());
return output;
}
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index b1abc59..acbc8ed 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -32,17 +32,34 @@
class MelReporter : public PatchCommandThread::PatchCommandListener {
public:
explicit MelReporter(AudioFlinger& audioFlinger)
- : mAudioFlinger(audioFlinger) {}
+ : mAudioFlinger(audioFlinger),
+ mSoundDoseManager(sp<SoundDoseManager>::make()) {}
- void onFirstRef() override {
- mAudioFlinger.mPatchCommandThread->addListener(this);
- }
+ void onFirstRef() override;
/** Returns true if we should compute MEL for the given device. */
bool shouldComputeMelForDeviceType(audio_devices_t device);
- // For now only support internal MelReporting
- [[nodiscard]] bool isHalReportingEnabled() const { return false; }
+ /**
+ * Activates the MEL reporting from the HAL sound dose interface. If the HAL
+ * does not support the sound dose interface for this module, the internal MEL
+ * calculation will be use.
+ *
+ * For now support internal MelReporting only if the sound dose standalone HAL
+ * is not implemented
+ *
+ * @return true if the MEL reporting will be done from the sound dose HAL
+ * interface
+ */
+ bool activateHalSoundDoseComputation(const std::string& module);
+
+ /**
+ * Activates the MEL reporting from internal framework values. These are used
+ * as a fallback when there is no sound dose interface implementation from HAL.
+ * Note: the internal CSD computation does not guarantee a certification with
+ * IEC62368-1 3rd edition or EN50332-3
+ */
+ void activateInternalSoundDoseComputation();
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
@@ -54,9 +71,17 @@
void onReleaseAudioPatch(audio_patch_handle_t handle) override;
private:
- AudioFlinger& mAudioFlinger; // does not own the object
+ void stopInternalMelComputation();
+ void stopInternalMelComputationForStream(audio_io_handle_t streamId);
- SoundDoseManager mSoundDoseManager;
+ void startMelComputationForNewPatch(audio_io_handle_t streamHandle,
+ audio_port_handle_t deviceId);
+
+ AudioFlinger& mAudioFlinger; // does not own the object
+ std::shared_ptr<::aidl::android::hardware::audio::sounddose::ISoundDoseFactory>
+ mSoundDoseFactory;
+
+ sp<SoundDoseManager> mSoundDoseManager;
struct ActiveMelPatch {
audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
@@ -70,4 +95,5 @@
std::mutex mLock;
std::unordered_map<audio_patch_handle_t, ActiveMelPatch>
mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock);
+ bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false;
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 9598ed9..3dcf932 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -273,8 +273,8 @@
static std::string toString(audio_latency_mode_t mode) {
// We convert to the AIDL type to print (eventually the legacy type will be removed).
- const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
- return result.has_value() ? media::toString(*result) : "UNKNOWN";
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
}
// Could be made a template, but other toString overloads for std::vector are confused.
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ac863b5..382e4f9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -440,7 +440,8 @@
return Status::ok();
}
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+ media::audio::common::AudioDualMonoMode* _aidl_return)
{
audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
const status_t status = mTrack->getDualMonoMode(&mode)
@@ -453,7 +454,7 @@
}
Status AudioFlinger::TrackHandle::setDualMonoMode(
- media::AudioDualMonoMode mode)
+ media::audio::common::AudioDualMonoMode mode)
{
const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -477,7 +478,7 @@
}
Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
- media::AudioPlaybackRate* _aidl_return)
+ media::audio::common::AudioPlaybackRate* _aidl_return)
{
audio_playback_rate_t localPlaybackRate{};
status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -490,7 +491,7 @@
}
Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
- const media::AudioPlaybackRate& playbackRate)
+ const media::audio::common::AudioPlaybackRate& playbackRate)
{
const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -792,7 +793,7 @@
" Format Chn mask SRate "
"ST Usg CT "
" G db L dB R dB VS dB "
- " Server FrmCnt FrmRdy F Underruns Flushed"
+ " Server FrmCnt FrmRdy F Underruns Flushed BitPerfect"
"%s\n",
isServerLatencySupported() ? " Latency" : "");
}
@@ -878,7 +879,7 @@
"%08X %08X %6u "
"%2u %3x %2x "
"%5.2g %5.2g %5.2g %5.2g%c "
- "%08X %6zu%c %6zu %c %9u%c %7u",
+ "%08X %6zu%c %6zu %c %9u%c %7u %10s",
active ? "yes" : "no",
(mClient == 0) ? getpid() : mClient->pid(),
mSessionId,
@@ -907,7 +908,8 @@
fillingStatus,
mAudioTrackServerProxy->getUnderrunFrames(),
nowInUnderrun,
- (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000
+ (unsigned)mAudioTrackServerProxy->framesFlushed() % 10000000,
+ isBitPerfect() ? "true" : "false"
);
if (isServerLatencySupported()) {
@@ -1160,6 +1162,23 @@
}
if (status == NO_ERROR) {
forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
+
+ // send format to AudioManager for playback activity monitoring
+ sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
+ if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
+ std::unique_ptr<os::PersistableBundle> bundle =
+ std::make_unique<os::PersistableBundle>();
+ bundle->putBoolean(String16(kExtraPlayerEventSpatializedKey),
+ isSpatialized());
+ bundle->putInt(String16(kExtraPlayerEventSampleRateKey), mSampleRate);
+ bundle->putInt(String16(kExtraPlayerEventChannelMaskKey), mChannelMask);
+ status_t result = audioManager->portEvent(mPortId,
+ PLAYER_UPDATE_FORMAT, bundle);
+ if (result != OK) {
+ ALOGE("%s: unable to send playback format for port ID %d, status error %d",
+ __func__, mPortId, result);
+ }
+ }
}
return status;
}
diff --git a/services/audioflinger/sounddose/Android.bp b/services/audioflinger/sounddose/Android.bp
index 0e409d3..6d9a0cc 100644
--- a/services/audioflinger/sounddose/Android.bp
+++ b/services/audioflinger/sounddose/Android.bp
@@ -12,15 +12,24 @@
double_loadable: true,
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_core_sounddose_ndk_shared",
+ "latest_android_hardware_audio_sounddose_ndk_shared",
+ ],
+
srcs: [
"SoundDoseManager.cpp",
],
shared_libs: [
"audioflinger-aidl-cpp",
+ "libaudio_aidl_conversion_common_ndk",
+ "libaudiofoundation",
"libaudioutils",
"libbase",
"libbinder",
+ "libbinder_ndk",
"liblog",
"libutils",
],
diff --git a/services/audioflinger/sounddose/SoundDoseManager.cpp b/services/audioflinger/sounddose/SoundDoseManager.cpp
index 61f27cb..df6eb5b 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.cpp
+++ b/services/audioflinger/sounddose/SoundDoseManager.cpp
@@ -20,14 +20,22 @@
#include "SoundDoseManager.h"
+#if !defined(BACKEND_NDK)
+#define BACKEND_NDK
+#endif
+
+#include "android/media/SoundDoseRecord.h"
#include <android-base/stringprintf.h>
+#include <media/AidlConversionCppNdk.h>
+#include <cinttypes>
#include <time.h>
#include <utils/Log.h>
-#include <cinttypes>
-#include "android/media/SoundDoseRecord.h"
namespace android {
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+
namespace {
int64_t getMonotonicSecond() {
@@ -46,6 +54,11 @@
size_t channelCount, audio_format_t format) {
std::lock_guard _l(mLock);
+ if (mHalSoundDose != nullptr) {
+ ALOGW("%s: using HAL MEL computation, no MelProcessor needed.", __func__);
+ return nullptr;
+ }
+
auto streamProcessor = mActiveProcessors.find(streamHandle);
sp<audio_utils::MelProcessor> processor;
if (streamProcessor != mActiveProcessors.end() &&
@@ -63,11 +76,54 @@
}
}
+bool SoundDoseManager::setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose) {
+ ALOGV("%s", __func__);
+
+ {
+ std::lock_guard _l(mLock);
+
+ mHalSoundDose = halSoundDose;
+ if (halSoundDose == nullptr) {
+ ALOGI("%s: passed ISoundDose object is null, switching to internal CSD", __func__);
+ return false;
+ }
+
+ if (!mHalSoundDose->setOutputRs2(mRs2Value).isOk()) {
+ ALOGW("%s: Cannot set RS2 value for momentary exposure %f",
+ __func__,
+ mRs2Value);
+ }
+
+ // initialize the HAL sound dose callback lazily
+ if (mHalSoundDoseCallback == nullptr) {
+ mHalSoundDoseCallback =
+ ndk::SharedRefBase::make<HalSoundDoseCallback>(this);
+ }
+ }
+
+ auto status = halSoundDose->registerSoundDoseCallback(mHalSoundDoseCallback);
+ if (!status.isOk()) {
+ // Not a warning since this can happen if the callback was registered before
+ ALOGI("%s: Cannot register HAL sound dose callback with status message: %s",
+ __func__,
+ status.getMessage());
+ }
+
+ return true;
+}
+
void SoundDoseManager::setOutputRs2(float rs2Value) {
ALOGV("%s", __func__);
std::lock_guard _l(mLock);
mRs2Value = rs2Value;
+ if (mHalSoundDose != nullptr) {
+ // using the HAL sound dose interface
+ if (!mHalSoundDose->setOutputRs2(mRs2Value).isOk()) {
+ ALOGE("%s: Cannot set RS2 value for momentary exposure %f", __func__, mRs2Value);
+ }
+ return;
+ }
for (auto& streamProcessor : mActiveProcessors) {
sp<audio_utils::MelProcessor> processor = streamProcessor.second.promote();
@@ -89,6 +145,103 @@
}
}
+audio_port_handle_t SoundDoseManager::getIdForAudioDevice(const AudioDevice& audioDevice) const {
+ std::lock_guard _l(mLock);
+
+ audio_devices_t type;
+ std::string address;
+ auto result = aidl::android::aidl2legacy_AudioDevice_audio_device(
+ audioDevice, &type, &address);
+ if (result != NO_ERROR) {
+ ALOGE("%s: could not convert from AudioDevice to AudioDeviceTypeAddr", __func__);
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+
+ auto adt = AudioDeviceTypeAddr(type, address);
+ auto deviceIt = mActiveDevices.find(adt);
+ if (deviceIt == mActiveDevices.end()) {
+ ALOGE("%s: could not find port id for device %s", __func__, adt.toString().c_str());
+ return AUDIO_PORT_HANDLE_NONE;
+ }
+ return deviceIt->second;
+}
+
+void SoundDoseManager::mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
+ const audio_port_handle_t deviceId) {
+ std::lock_guard _l(mLock);
+ ALOGI("%s: map address: %s to device id: %d", __func__, adt.toString().c_str(), deviceId);
+ mActiveDevices[adt] = deviceId;
+}
+
+void SoundDoseManager::clearMapDeviceIdEntries(audio_port_handle_t deviceId) {
+ std::lock_guard _l(mLock);
+ for (auto activeDevice = mActiveDevices.begin(); activeDevice != mActiveDevices.end();) {
+ if (activeDevice->second == deviceId) {
+ ALOGI("%s: clear mapping addr: %s to deviceId: %d",
+ __func__, activeDevice->first.toString().c_str(), deviceId);
+ activeDevice = mActiveDevices.erase(activeDevice);
+ continue;
+ }
+ ++activeDevice;
+ }
+ return;
+}
+
+ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onMomentaryExposureWarning(
+ float in_currentDbA, const AudioDevice& in_audioDevice) {
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ std::shared_ptr<ISoundDose> halSoundDose;
+ soundDoseManager->getHalSoundDose(&halSoundDose);
+ if(halSoundDose == nullptr) {
+ ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
+ if (id == AUDIO_PORT_HANDLE_NONE) {
+ ALOGW("%s: no mapped id for audio device with type %d and address %s",
+ __func__, in_audioDevice.type.type,
+ in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ soundDoseManager->onMomentaryExposure(in_currentDbA, id);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus SoundDoseManager::HalSoundDoseCallback::onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const AudioDevice& in_audioDevice) {
+ auto soundDoseManager = mSoundDoseManager.promote();
+ if (soundDoseManager == nullptr) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ std::shared_ptr<ISoundDose> halSoundDose;
+ soundDoseManager->getHalSoundDose(&halSoundDose);
+ if(halSoundDose == nullptr) {
+ ALOGW("%s: HAL sound dose interface deactivated. Ignoring", __func__);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+
+ auto id = soundDoseManager->getIdForAudioDevice(in_audioDevice);
+ if (id == AUDIO_PORT_HANDLE_NONE) {
+ ALOGW("%s: no mapped id for audio device with type %d and address %s",
+ __func__, in_audioDevice.type.type,
+ in_audioDevice.address.get<AudioDeviceAddress::id>().c_str());
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ // TODO: introduce timestamp in onNewMelValues callback
+ soundDoseManager->onNewMelValues(in_melRecord.melValues, 0,
+ in_melRecord.melValues.size(), id);
+
+ return ndk::ScopedAStatus::ok();
+}
+
void SoundDoseManager::SoundDose::binderDied(__unused const wp<IBinder>& who) {
ALOGV("%s", __func__);
@@ -156,11 +309,14 @@
}
void SoundDoseManager::setUseFrameworkMel(bool useFrameworkMel) {
+ // invalidate any HAL sound dose interface used
+ setHalSoundDoseInterface(nullptr);
+
std::lock_guard _l(mLock);
mUseFrameworkMel = useFrameworkMel;
}
-bool SoundDoseManager::useFrameworkMel() const {
+bool SoundDoseManager::forceUseFrameworkMel() const {
std::lock_guard _l(mLock);
return mUseFrameworkMel;
}
@@ -170,11 +326,16 @@
mComputeCsdOnAllDevices = computeCsdOnAllDevices;
}
-bool SoundDoseManager::computeCsdOnAllDevices() const {
+bool SoundDoseManager::forceComputeCsdOnAllDevices() const {
std::lock_guard _l(mLock);
return mComputeCsdOnAllDevices;
}
+void SoundDoseManager::getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const {
+ std::lock_guard _l(mLock);
+ *halSoundDose = mHalSoundDose;
+}
+
void SoundDoseManager::resetSoundDose() {
std::lock_guard lock(mLock);
mSoundDose = nullptr;
diff --git a/services/audioflinger/sounddose/SoundDoseManager.h b/services/audioflinger/sounddose/SoundDoseManager.h
index eb5fa49..b10874f 100644
--- a/services/audioflinger/sounddose/SoundDoseManager.h
+++ b/services/audioflinger/sounddose/SoundDoseManager.h
@@ -17,8 +17,11 @@
#pragma once
+#include <aidl/android/hardware/audio/core/ISoundDose.h>
+#include <aidl/android/media/audio/common/AudioDevice.h>
#include <android/media/BnSoundDose.h>
#include <android/media/ISoundDoseCallback.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <audio_utils/MelAggregator.h>
#include <audio_utils/MelProcessor.h>
#include <binder/Status.h>
@@ -27,8 +30,10 @@
namespace android {
+using aidl::android::hardware::audio::core::ISoundDose;
+
class SoundDoseManager : public audio_utils::MelProcessor::MelCallback {
- public:
+public:
/** CSD is computed with a rolling window of 7 days. */
static constexpr int64_t kCsdWindowSeconds = 604800; // 60s * 60m * 24h * 7d
/** Default RS2 value in dBA as defined in IEC 62368-1 3rd edition. */
@@ -36,13 +41,13 @@
SoundDoseManager()
: mMelAggregator(sp<audio_utils::MelAggregator>::make(kCsdWindowSeconds)),
- mRs2Value(kDefaultRs2Value){};
+ mRs2Value(kDefaultRs2Value) {};
/**
* \brief Creates or gets the MelProcessor assigned to the streamHandle
*
* \param deviceId id for the devices where the stream is active.
- * \param streanHandle handle to the stream
+ * \param streamHandle handle to the stream
* \param sampleRate sample rate for the processor
* \param channelCount number of channels to be processed.
* \param format format of the input samples.
@@ -58,7 +63,7 @@
/**
* \brief Removes stream processor when MEL computation is not needed anymore
*
- * \param streanHandle handle to the stream
+ * \param streamHandle handle to the stream
*/
void removeStreamProcessor(audio_io_handle_t streamHandle);
@@ -78,13 +83,31 @@
**/
sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
+ /**
+ * Sets the HAL sound dose interface to use for the MEL computation. Use nullptr
+ * for using the internal MEL computation.
+ *
+ * @return true if setting the HAL sound dose value was successful, false otherwise.
+ */
+ bool setHalSoundDoseInterface(const std::shared_ptr<ISoundDose>& halSoundDose);
+
+ /** Returns the cached audio port id from the active devices. */
+ audio_port_handle_t getIdForAudioDevice(
+ const aidl::android::media::audio::common::AudioDevice& audioDevice) const;
+
+ /** Caches mapping between address and device port id. */
+ void mapAddressToDeviceId(const AudioDeviceTypeAddr& adt,
+ const audio_port_handle_t deviceId);
+
+ /** Clear all map entries with passed audio_port_handle_t. */
+ void clearMapDeviceIdEntries(audio_port_handle_t deviceId);
+
std::string dump() const;
- // used for testing
+ // used for testing only
size_t getCachedMelRecordsSize() const;
- bool useFrameworkMel() const;
- bool computeCsdOnAllDevices() const;
-
+ bool forceUseFrameworkMel() const;
+ bool forceComputeCsdOnAllDevices() const;
/** Method for converting from audio_utils::CsdRecord to media::SoundDoseRecord. */
static media::SoundDoseRecord csdRecordToSoundDoseRecord(const audio_utils::CsdRecord& legacy);
@@ -101,7 +124,7 @@
public:
SoundDose(SoundDoseManager* manager, const sp<media::ISoundDoseCallback>& callback)
: mSoundDoseManager(manager),
- mSoundDoseCallback(callback) {};
+ mSoundDoseCallback(callback) {}
/** IBinder::DeathRecipient. Listen to the death of ISoundDoseCallback. */
virtual void binderDied(const wp<IBinder>& who);
@@ -119,6 +142,21 @@
const sp<media::ISoundDoseCallback> mSoundDoseCallback;
};
+ class HalSoundDoseCallback : public ISoundDose::BnHalSoundDoseCallback {
+ public:
+ explicit HalSoundDoseCallback(SoundDoseManager* manager)
+ : mSoundDoseManager(manager) {}
+
+ ndk::ScopedAStatus onMomentaryExposureWarning(
+ float in_currentDbA,
+ const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
+ ndk::ScopedAStatus onNewMelValues(
+ const ISoundDose::IHalSoundDoseCallback::MelRecord& in_melRecord,
+ const aidl::android::media::audio::common::AudioDevice& in_audioDevice) override;
+
+ wp<SoundDoseManager> mSoundDoseManager;
+ };
+
void resetSoundDose();
void resetCsd(float currentCsd, const std::vector<media::SoundDoseRecord>& records);
@@ -127,6 +165,8 @@
void setUseFrameworkMel(bool useFrameworkMel);
void setComputeCsdOnAllDevices(bool computeCsdOnAllDevices);
+ /** Returns the HAL sound dose interface or null if internal MEL computation is used. */
+ void getHalSoundDose(std::shared_ptr<ISoundDose>* halSoundDose) const;
mutable std::mutex mLock;
@@ -136,12 +176,18 @@
std::unordered_map<audio_io_handle_t, wp<audio_utils::MelProcessor>> mActiveProcessors
GUARDED_BY(mLock);
+ // map active device address and type to device id
+ std::map<AudioDeviceTypeAddr, audio_port_handle_t> mActiveDevices GUARDED_BY(mLock);
+
float mRs2Value GUARDED_BY(mLock);
sp<SoundDose> mSoundDose GUARDED_BY(mLock);
- bool mUseFrameworkMel GUARDED_BY(mLock);
- bool mComputeCsdOnAllDevices GUARDED_BY(mLock);
+ std::shared_ptr<ISoundDose> mHalSoundDose GUARDED_BY(mLock);
+ std::shared_ptr<HalSoundDoseCallback> mHalSoundDoseCallback GUARDED_BY(mLock);
+
+ bool mUseFrameworkMel GUARDED_BY(mLock) = false;
+ bool mComputeCsdOnAllDevices GUARDED_BY(mLock) = false;
};
} // namespace android
diff --git a/services/audioflinger/sounddose/tests/Android.bp b/services/audioflinger/sounddose/tests/Android.bp
index a886663..fef73dc 100644
--- a/services/audioflinger/sounddose/tests/Android.bp
+++ b/services/audioflinger/sounddose/tests/Android.bp
@@ -14,15 +14,24 @@
"sounddosemanager_tests.cpp"
],
+ defaults: [
+ "latest_android_media_audio_common_types_ndk_static",
+ "latest_android_hardware_audio_core_sounddose_ndk_static",
+ "latest_android_hardware_audio_sounddose_ndk_static",
+ ],
+
shared_libs: [
"audioflinger-aidl-cpp",
+ "libaudiofoundation",
"libaudioutils",
"libbase",
+ "libbinder_ndk",
"liblog",
"libutils",
],
static_libs: [
+ "libaudio_aidl_conversion_common_ndk",
"libgmock",
"libsounddose",
],
@@ -37,4 +46,8 @@
"-Werror",
"-Wextra",
],
+
+ test_suites: [
+ "general-tests",
+ ],
}
\ No newline at end of file
diff --git a/services/audioflinger/sounddose/tests/TEST_MAPPING b/services/audioflinger/sounddose/tests/TEST_MAPPING
new file mode 100644
index 0000000..dd7fe4d
--- /dev/null
+++ b/services/audioflinger/sounddose/tests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "sounddosemanager_tests"
+ }
+ ]
+}
diff --git a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
index 0aa5a20..ba2edcf 100644
--- a/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
+++ b/services/audioflinger/sounddose/tests/sounddosemanager_tests.cpp
@@ -15,25 +15,55 @@
*/
// #define LOG_NDEBUG 0
-#define LOG_TAG "sounddosemanager_tests"
+#define LOG_TAG "SoundDoseManager_tests"
+
+#include <aidl/android/hardware/audio/core/BnSoundDose.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
#include <SoundDoseManager.h>
-#include <gtest/gtest.h>
-
namespace android {
namespace {
-TEST(SoundDoseManagerTest, GetProcessorForExistingStream) {
- SoundDoseManager soundDoseManager;
+using aidl::android::hardware::audio::core::BnSoundDose;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
+
+class HalSoundDoseMock : public BnSoundDose {
+public:
+ MOCK_METHOD(ndk::ScopedAStatus, getOutputRs2, (float*), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, setOutputRs2, (float), (override));
+ MOCK_METHOD(ndk::ScopedAStatus, registerSoundDoseCallback,
+ (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>&), (override));
+};
+
+class SoundDoseManagerTest : public ::testing::Test {
+protected:
+ void SetUp() override {
+ mSoundDoseManager = sp<SoundDoseManager>::make();
+ mHalSoundDose = ndk::SharedRefBase::make<HalSoundDoseMock>();
+
+ ON_CALL(*mHalSoundDose.get(), setOutputRs2)
+ .WillByDefault([] (float rs2) {
+ EXPECT_EQ(rs2, ISoundDose::DEFAULT_MAX_RS2);
+ return ndk::ScopedAStatus::ok();
+ });
+ }
+
+ sp<SoundDoseManager> mSoundDoseManager;
+ std::shared_ptr<HalSoundDoseMock> mHalSoundDose;
+};
+
+TEST_F(SoundDoseManagerTest, GetProcessorForExistingStream) {
sp<audio_utils::MelProcessor> processor1 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
sp<audio_utils::MelProcessor> processor2 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
@@ -42,18 +72,17 @@
EXPECT_EQ(processor1, processor2);
}
-TEST(SoundDoseManagerTest, RemoveExistingStream) {
- SoundDoseManager soundDoseManager;
+TEST_F(SoundDoseManagerTest, RemoveExistingStream) {
sp<audio_utils::MelProcessor> processor1 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/1,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/1,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
/*format*/AUDIO_FORMAT_PCM_FLOAT);
- soundDoseManager.removeStreamProcessor(1);
+ mSoundDoseManager->removeStreamProcessor(1);
sp<audio_utils::MelProcessor> processor2 =
- soundDoseManager.getOrCreateProcessorForDevice(/*deviceId=*/2,
+ mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
/*streamHandle=*/1,
/*sampleRate*/44100,
/*channelCount*/2,
@@ -62,13 +91,150 @@
EXPECT_NE(processor1, processor2);
}
-TEST(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
- SoundDoseManager soundDoseManager;
+TEST_F(SoundDoseManagerTest, NewMelValuesCacheNewRecord) {
std::vector<float>mels{1, 1};
- soundDoseManager.onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
+ mSoundDoseManager->onNewMelValues(mels, 0, mels.size(), /*deviceId=*/1);
- EXPECT_EQ(soundDoseManager.getCachedMelRecordsSize(), size_t{1});
+ EXPECT_EQ(mSoundDoseManager->getCachedMelRecordsSize(), size_t{1});
+}
+
+TEST_F(SoundDoseManagerTest, InvalidHalInterfaceIsNotSet) {
+ EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+}
+
+TEST_F(SoundDoseManagerTest, SetHalSoundDoseDisablesNewMelProcessorCallbacks) {
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ EXPECT_NE(nullptr, callback);
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+ EXPECT_EQ(nullptr, mSoundDoseManager->getOrCreateProcessorForDevice(/*deviceId=*/2,
+ /*streamHandle=*/1,
+ /*sampleRate*/44100,
+ /*channelCount*/2,
+ /*format*/AUDIO_FORMAT_PCM_FLOAT));
+}
+
+TEST_F(SoundDoseManagerTest, SetHalSoundDoseRegistersHalCallbacks) {
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ EXPECT_NE(nullptr, callback);
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+}
+
+TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalWithNoAddressIllegalArgument) {
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ halCallback = callback;
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+ EXPECT_NE(nullptr, halCallback);
+ AudioDevice audioDevice = {};
+ audioDevice.address.set<AudioDeviceAddress::id>("test");
+ auto status = halCallback->onMomentaryExposureWarning(
+ /*in_currentDbA=*/101.f, audioDevice);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, MomentaryExposureFromHalAfterInternalSelectedReturnsException) {
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ halCallback = callback;
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+ EXPECT_NE(nullptr, halCallback);
+ EXPECT_FALSE(mSoundDoseManager->setHalSoundDoseInterface(nullptr));
+
+ AudioDevice audioDevice = {};
+ audioDevice.address.set<AudioDeviceAddress::id>("test");
+ auto status = halCallback->onMomentaryExposureWarning(
+ /*in_currentDbA=*/101.f, audioDevice);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, OnNewMelValuesFromHalWithNoAddressIllegalArgument) {
+ std::shared_ptr<ISoundDose::IHalSoundDoseCallback> halCallback;
+
+ EXPECT_CALL(*mHalSoundDose.get(), setOutputRs2).Times(1);
+ EXPECT_CALL(*mHalSoundDose.get(), registerSoundDoseCallback)
+ .Times(1)
+ .WillOnce([&] (const std::shared_ptr<ISoundDose::IHalSoundDoseCallback>& callback) {
+ halCallback = callback;
+ return ndk::ScopedAStatus::ok();
+ });
+
+ EXPECT_TRUE(mSoundDoseManager->setHalSoundDoseInterface(mHalSoundDose));
+
+ EXPECT_NE(nullptr, halCallback);
+ AudioDevice audioDevice = {};
+ audioDevice.address.set<AudioDeviceAddress::id>("test");
+ auto status = halCallback->onNewMelValues(/*in_melRecord=*/{}, audioDevice);
+ EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(SoundDoseManagerTest, GetIdReturnsMappedAddress) {
+ const std::string address = "testAddress";
+ const audio_port_handle_t deviceId = 2;
+ const AudioDeviceTypeAddr adt{audio_devices_t{0}, address};
+ AudioDevice audioDevice;
+ audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
+
+ EXPECT_EQ(deviceId, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetAfterClearIdReturnsNone) {
+ const std::string address = "testAddress";
+ const AudioDeviceTypeAddr adt {audio_devices_t{0}, address};
+ const audio_port_handle_t deviceId = 2;
+ AudioDevice audioDevice;
+ audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+ mSoundDoseManager->mapAddressToDeviceId(adt, deviceId);
+ mSoundDoseManager->clearMapDeviceIdEntries(deviceId);
+
+ EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetUnmappedIdReturnsHandleNone) {
+ const std::string address = "testAddress";
+ AudioDevice audioDevice;
+ audioDevice.address.set<AudioDeviceAddress::id>(address);
+
+ EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, mSoundDoseManager->getIdForAudioDevice(audioDevice));
+}
+
+TEST_F(SoundDoseManagerTest, GetDefaultForceComputeCsdOnAllDevices) {
+ EXPECT_FALSE(mSoundDoseManager->forceComputeCsdOnAllDevices());
+}
+
+TEST_F(SoundDoseManagerTest, GetDefaultForceUseFrameworkMel) {
+ EXPECT_FALSE(mSoundDoseManager->forceUseFrameworkMel());
}
} // namespace
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 1d4eb1e..f99f76e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1280,17 +1280,26 @@
info = getPreferredMixerAttributesInfo(
outputDevices.itemAt(0)->getId(),
mEngine->getProductStrategyForAttributes(*resultAttr));
- if (info != nullptr && info->getUid() != uid && info->getActiveClientCount() == 0) {
- // Only use preferred mixer when the requested uid matched or
- // there is active client on preferred mixer.
+ // Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect
+ // and it is currently active.
+ if (info != nullptr && info->getUid() != uid &&
+ ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) == AUDIO_OUTPUT_FLAG_NONE ||
+ info->getActiveClientCount() == 0)) {
info = nullptr;
}
}
*output = getOutputForDevices(outputDevices, session, resultAttr, config,
flags, isSpatialized, info, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
+ // The client will be active if the client is currently preferred mixer owner and the
+ // requested configuration matches the preferred mixer configuration.
*isBitPerfect = (info != nullptr
&& (info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
- && *output != AUDIO_IO_HANDLE_NONE);
+ && info->getUid() == uid
+ && *output != AUDIO_IO_HANDLE_NONE
+ // When bit-perfect output is selected for the preferred mixer attributes owner,
+ // only need to consider the config matches.
+ && mOutputs.valueFor(*output)->isConfigurationMatched(
+ clientConfig, AUDIO_OUTPUT_FLAG_NONE));
}
if (*output == AUDIO_IO_HANDLE_NONE) {
AudioProfileVector profiles;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index 3e4dd69..ccbbf66 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
#include <android/media/SpatializationLevel.h>
#include <android/media/SpatializationMode.h>
#include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
#include <audio_utils/SimpleLog.h>
#include <math.h>
#include <media/AudioEffect.h>
@@ -167,8 +168,9 @@
static std::string toString(audio_latency_mode_t mode) {
// We convert to the AIDL type to print (eventually the legacy type will be removed).
- const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
- return result.has_value() ? media::toString(*result) : "unknown_latency_mode";
+ const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+ return result.has_value() ?
+ media::audio::common::toString(*result) : "unknown_latency_mode";
}
/**
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7f5c7a5..3f38d01 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -161,7 +161,8 @@
audio_port_handle_t *portId = nullptr,
audio_attributes_t attr = {},
audio_session_t session = AUDIO_SESSION_NONE,
- int uid = 0);
+ int uid = 0,
+ bool* isBitPerfect = nullptr);
void getInputForAttr(
const audio_attributes_t &attr,
audio_session_t session,
@@ -246,7 +247,8 @@
audio_port_handle_t *portId,
audio_attributes_t attr,
audio_session_t session,
- int uid) {
+ int uid,
+ bool* isBitPerfect) {
audio_io_handle_t localOutput;
if (!output) output = &localOutput;
*output = AUDIO_IO_HANDLE_NONE;
@@ -260,14 +262,15 @@
*portId = AUDIO_PORT_HANDLE_NONE;
AudioPolicyInterface::output_type_t outputType;
bool isSpatialized;
- bool isBitPerfect;
+ bool isBitPerfectInternal;
// TODO b/182392769: use attribution source util
AttributionSourceState attributionSource = AttributionSourceState();
attributionSource.uid = uid;
attributionSource.token = sp<BBinder>::make();
ASSERT_EQ(OK, mManager->getOutputForAttr(
&attr, output, session, &stream, attributionSource, &config, &flags,
- selectedDeviceId, portId, {}, &outputType, &isSpatialized, &isBitPerfect));
+ selectedDeviceId, portId, {}, &outputType, &isSpatialized,
+ isBitPerfect == nullptr ? &isBitPerfectInternal : isBitPerfect));
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
ASSERT_NE(AUDIO_IO_HANDLE_NONE, *output);
}
@@ -1119,6 +1122,116 @@
"", "", AUDIO_FORMAT_LDAC));
}
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, BitPerfectPlayback) {
+ const audio_format_t bitPerfectFormat = AUDIO_FORMAT_PCM_16_BIT;
+ const audio_channel_mask_t bitPerfectChannelMask = AUDIO_CHANNEL_OUT_QUAD;
+ const uint32_t bitPerfectSampleRate = 48000;
+ mClient->addSupportedFormat(bitPerfectFormat);
+ mClient->addSupportedChannelMask(bitPerfectChannelMask);
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "", "", AUDIO_FORMAT_DEFAULT));
+ auto devices = mManager->getAvailableOutputDevices();
+ audio_port_handle_t usbPortId = AUDIO_PORT_HANDLE_NONE;
+ for (auto device : devices) {
+ if (device->type() == AUDIO_DEVICE_OUT_USB_DEVICE) {
+ usbPortId = device->getId();
+ break;
+ }
+ }
+ EXPECT_NE(AUDIO_PORT_HANDLE_NONE, usbPortId);
+
+ const uid_t uid = 1234;
+ const uid_t anotherUid = 5678;
+ const audio_attributes_t mediaAttr = {
+ .content_type = AUDIO_CONTENT_TYPE_MUSIC,
+ .usage = AUDIO_USAGE_MEDIA,
+ };
+
+ std::vector<audio_mixer_attributes_t> mixerAttributes;
+ EXPECT_EQ(NO_ERROR, mManager->getSupportedMixerAttributes(usbPortId, mixerAttributes));
+ EXPECT_GT(mixerAttributes.size(), 0);
+ size_t bitPerfectIndex = 0;
+ for (; bitPerfectIndex < mixerAttributes.size(); ++bitPerfectIndex) {
+ if (mixerAttributes[bitPerfectIndex].mixer_behavior == AUDIO_MIXER_BEHAVIOR_BIT_PERFECT) {
+ break;
+ }
+ }
+ EXPECT_LT(bitPerfectIndex, mixerAttributes.size());
+ EXPECT_EQ(bitPerfectFormat, mixerAttributes[bitPerfectIndex].config.format);
+ EXPECT_EQ(bitPerfectChannelMask, mixerAttributes[bitPerfectIndex].config.channel_mask);
+ EXPECT_EQ(bitPerfectSampleRate, mixerAttributes[bitPerfectIndex].config.sample_rate);
+ EXPECT_EQ(NO_ERROR,
+ mManager->setPreferredMixerAttributes(
+ &mediaAttr, usbPortId, uid, &mixerAttributes[bitPerfectIndex]));
+
+ audio_io_handle_t bitPerfectOutput = AUDIO_IO_HANDLE_NONE;
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t bitPerfectPortId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+ bool isBitPerfect;
+
+ // When there is no active bit-perfect playback, the output selection will follow default
+ // routing strategy.
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+ uid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_NE(AUDIO_IO_HANDLE_NONE, output);
+ const auto outputDesc = mManager->getOutputs().valueFor(output);
+ EXPECT_NE(nullptr, outputDesc);
+ EXPECT_NE(AUDIO_OUTPUT_FLAG_BIT_PERFECT, outputDesc->mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+
+ // Start bit-perfect playback
+ getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+ bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &bitPerfectOutput, &bitPerfectPortId,
+ mediaAttr, AUDIO_SESSION_NONE, uid, &isBitPerfect);
+ status_t status = mManager->startOutput(bitPerfectPortId);
+ if (status == DEAD_OBJECT) {
+ getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+ bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &bitPerfectOutput, &bitPerfectPortId,
+ mediaAttr, AUDIO_SESSION_NONE, uid, &isBitPerfect);
+ status = mManager->startOutput(bitPerfectPortId);
+ }
+ EXPECT_EQ(NO_ERROR, status);
+ EXPECT_TRUE(isBitPerfect);
+ EXPECT_NE(AUDIO_IO_HANDLE_NONE, bitPerfectOutput);
+ const auto bitPerfectOutputDesc = mManager->getOutputs().valueFor(bitPerfectOutput);
+ EXPECT_NE(nullptr, bitPerfectOutputDesc);
+ EXPECT_EQ(AUDIO_OUTPUT_FLAG_BIT_PERFECT,
+ bitPerfectOutputDesc->mFlags & AUDIO_OUTPUT_FLAG_BIT_PERFECT);
+
+ // If the playback is from preferred mixer attributes owner but the request doesn't match
+ // preferred mixer attributes, it will not be bit-perfect.
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+ uid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, output);
+
+ // When bit-perfect playback is active, all other playback will be routed to bit-perfect output.
+ getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ 48000, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr, AUDIO_SESSION_NONE,
+ anotherUid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, output);
+
+ // When configuration matches preferred mixer attributes, which is bit-perfect, but the client
+ // is not the owner of preferred mixer attributes, the playback will not be bit-perfect.
+ getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,
+ bitPerfectSampleRate, AUDIO_OUTPUT_FLAG_NONE, &output, &portId, mediaAttr,
+ AUDIO_SESSION_NONE, anotherUid, &isBitPerfect);
+ EXPECT_FALSE(isBitPerfect);
+ EXPECT_EQ(bitPerfectOutput, output);
+
+ EXPECT_EQ(NO_ERROR,
+ mManager->clearPreferredMixerAttributes(&mediaAttr, usbPortId, uid));
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_USB_DEVICE,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "", "", AUDIO_FORMAT_LDAC));
+}
+
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
protected:
void TearDown() override;
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index c937d3a..2eb771d 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -54,7 +54,7 @@
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
- <mixPort name="hifi_output" role="source"/>
+ <mixPort name="hifi_output" role="source" flags="AUDIO_OUTPUT_FLAG_BIT_PERFECT"/>
</mixPorts>
<devicePorts>
<devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">