audio: add implementation for TV related API
1. TunerConfiguration.
2. AudioDescriptionMixLevel getter/setter.
3. DualMonoMode getter/setter.
4. PlaybackRate getter/setter.
Test: TIS player with instrumented HAL
Test: atest AudioTrackTest#testTunerConfiguration
Test: atest AudioTrackTest#testDualMonoMode
Test: atest AudioTrackTest#testAudioDescriptionMixLevel
Test: atest AudioManagerTest#testGetAdditionalOutputDeviceDelay
Bug: 173482792
Change-Id: Idb22ce6714fa240b2b4b3b8637b16d3a51228fa1
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 1ff4678..4c0db3e 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -2127,4 +2127,78 @@
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;
+}
+
} // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index a1708ee..004ae39 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -295,6 +295,7 @@
"aidl/android/media/AudioConfigBase.aidl",
"aidl/android/media/AudioContentType.aidl",
"aidl/android/media/AudioDevice.aidl",
+ "aidl/android/media/AudioDualMonoMode.aidl",
"aidl/android/media/AudioEncapsulationMode.aidl",
"aidl/android/media/AudioEncapsulationMetadataType.aidl",
"aidl/android/media/AudioFlag.aidl",
@@ -310,6 +311,7 @@
"aidl/android/media/AudioOffloadInfo.aidl",
"aidl/android/media/AudioOutputFlags.aidl",
"aidl/android/media/AudioPatch.aidl",
+ "aidl/android/media/AudioPlaybackRate.aidl",
"aidl/android/media/AudioPort.aidl",
"aidl/android/media/AudioPortConfig.aidl",
"aidl/android/media/AudioPortConfigType.aidl",
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index b1eb950..57bd04f 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -51,6 +51,8 @@
#define WAIT_STREAM_END_TIMEOUT_SEC 120
static const int kMaxLoopCountNotifications = 32;
+using ::android::aidl_utils::statusTFromBinderStatus;
+
namespace android {
// ---------------------------------------------------------------------------
@@ -1096,6 +1098,53 @@
return mOriginalSampleRate;
}
+status_t AudioTrack::setDualMonoMode(audio_dual_mono_mode_t mode)
+{
+ AutoMutex lock(mLock);
+ return setDualMonoMode_l(mode);
+}
+
+status_t AudioTrack::setDualMonoMode_l(audio_dual_mono_mode_t mode)
+{
+ const status_t status = statusTFromBinderStatus(
+ mAudioTrack->setDualMonoMode(VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode))));
+ if (status == NO_ERROR) mDualMonoMode = mode;
+ return status;
+}
+
+status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
+{
+ AutoMutex lock(mLock);
+ media::AudioDualMonoMode mediaMode;
+ const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
+ if (status == NO_ERROR) {
+ *mode = VALUE_OR_RETURN_STATUS(
+ aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mediaMode));
+ }
+ return status;
+}
+
+status_t AudioTrack::setAudioDescriptionMixLevel(float leveldB)
+{
+ AutoMutex lock(mLock);
+ return setAudioDescriptionMixLevel_l(leveldB);
+}
+
+status_t AudioTrack::setAudioDescriptionMixLevel_l(float leveldB)
+{
+ const status_t status = statusTFromBinderStatus(
+ mAudioTrack->setAudioDescriptionMixLevel(leveldB));
+ if (status == NO_ERROR) mAudioDescriptionMixLeveldB = leveldB;
+ return status;
+}
+
+status_t AudioTrack::getAudioDescriptionMixLevel(float* leveldB) const
+{
+ AutoMutex lock(mLock);
+ return statusTFromBinderStatus(mAudioTrack->getAudioDescriptionMixLevel(leveldB));
+}
+
status_t AudioTrack::setPlaybackRate(const AudioPlaybackRate &playbackRate)
{
AutoMutex lock(mLock);
@@ -1103,7 +1152,13 @@
return NO_ERROR;
}
if (isOffloadedOrDirect_l()) {
- return INVALID_OPERATION;
+ const status_t status = statusTFromBinderStatus(mAudioTrack->setPlaybackRateParameters(
+ VALUE_OR_RETURN_STATUS(
+ legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate))));
+ if (status == NO_ERROR) {
+ mPlaybackRate = playbackRate;
+ }
+ return status;
}
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
return INVALID_OPERATION;
@@ -1168,9 +1223,18 @@
return NO_ERROR;
}
-const AudioPlaybackRate& AudioTrack::getPlaybackRate() const
+const AudioPlaybackRate& AudioTrack::getPlaybackRate()
{
AutoMutex lock(mLock);
+ if (isOffloadedOrDirect_l()) {
+ media::AudioPlaybackRate playbackRateTemp;
+ const status_t status = statusTFromBinderStatus(
+ mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
+ if (status == NO_ERROR) { // update local version if changed.
+ mPlaybackRate =
+ aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRateTemp).value();
+ }
+ }
return mPlaybackRate;
}
@@ -1771,6 +1835,13 @@
mProxy->setPlaybackRate(playbackRateTemp);
mProxy->setMinimum(mNotificationFramesAct);
+ if (mDualMonoMode != AUDIO_DUAL_MONO_MODE_OFF) {
+ setDualMonoMode_l(mDualMonoMode);
+ }
+ if (mAudioDescriptionMixLeveldB != -std::numeric_limits<float>::infinity()) {
+ setAudioDescriptionMixLevel_l(mAudioDescriptionMixLeveldB);
+ }
+
mDeathNotifier = new DeathNotifier(this);
IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
new file mode 100644
index 0000000..f6220c2
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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
new file mode 100644
index 0000000..e29d398
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index 2b6c362..ac58925 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,6 +16,8 @@
package android.media;
+import android.media.AudioDualMonoMode;
+import android.media.AudioPlaybackRate;
import android.media.AudioTimestampInternal;
import android.media.SharedFileRegion;
import android.media.VolumeShaperConfiguration;
@@ -81,4 +83,34 @@
/** Gets the volume shaper state. */
@nullable VolumeShaperState getVolumeShaperState(int id);
+
+ /**
+ * Returns DualMonoMode setting associated with this AudioTrack.
+ */
+ AudioDualMonoMode getDualMonoMode();
+
+ /**
+ * Sets DualMonoMode setting.
+ */
+ void setDualMonoMode(in AudioDualMonoMode mode);
+
+ /**
+ * Returns the AudioDescriptionMixLevel.
+ */
+ float getAudioDescriptionMixLevel();
+
+ /**
+ * Sets the AudioDescriptionMixLevel.
+ */
+ void setAudioDescriptionMixLevel(float leveldB);
+
+ /**
+ * Returns the AudioPlaybackRate.
+ */
+ AudioPlaybackRate getPlaybackRateParameters();
+
+ /**
+ * Sets the AudioPlaybackRate.
+ */
+ void setPlaybackRateParameters(in AudioPlaybackRate playbackRate);
}
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 56afe93..bde20cd 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -25,6 +25,7 @@
#include <android/media/AudioClient.h>
#include <android/media/AudioConfig.h>
#include <android/media/AudioConfigBase.h>
+#include <android/media/AudioDualMonoMode.h>
#include <android/media/AudioEncapsulationMode.h>
#include <android/media/AudioEncapsulationMetadataType.h>
#include <android/media/AudioFlag.h>
@@ -36,6 +37,7 @@
#include <android/media/AudioMixLatencyClass.h>
#include <android/media/AudioMode.h>
#include <android/media/AudioOutputFlags.h>
+#include <android/media/AudioPlaybackRate.h>
#include <android/media/AudioPort.h>
#include <android/media/AudioPortConfigType.h>
#include <android/media/AudioPortDeviceExt.h>
@@ -359,4 +361,24 @@
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);
+
} // namespace android
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 3728a16..d2696c7 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -515,6 +515,18 @@
*/
uint32_t getOriginalSampleRate() const;
+ /* Sets the Dual Mono mode presentation on the output device. */
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode);
+
+ /* Returns the Dual Mono mode presentation setting. */
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const;
+
+ /* Sets the Audio Description Mix level in dB. */
+ status_t setAudioDescriptionMixLevel(float leveldB);
+
+ /* Returns the Audio Description Mix level in dB. */
+ status_t getAudioDescriptionMixLevel(float* leveldB) const;
+
/* Set source playback rate for timestretch
* 1.0 is normal speed: < 1.0 is slower, > 1.0 is faster
* 1.0 is normal pitch: < 1.0 is lower pitch, > 1.0 is higher pitch
@@ -528,7 +540,7 @@
status_t setPlaybackRate(const AudioPlaybackRate &playbackRate);
/* Return current playback rate */
- const AudioPlaybackRate& getPlaybackRate() const;
+ const AudioPlaybackRate& getPlaybackRate();
/* Enables looping and sets the start and end points of looping.
* Only supported for static buffer mode.
@@ -1072,6 +1084,12 @@
void updateRoutedDeviceId_l();
+ /* Sets the Dual Mono mode presentation on the output device. */
+ status_t setDualMonoMode_l(audio_dual_mono_mode_t mode);
+
+ /* Sets the Audio Description Mix level in dB. */
+ status_t setAudioDescriptionMixLevel_l(float leveldB);
+
// Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
sp<media::IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
@@ -1284,6 +1302,10 @@
wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+ // Cached values to restore along with the AudioTrack.
+ audio_dual_mono_mode_t mDualMonoMode = AUDIO_DUAL_MONO_MODE_OFF;
+ float mAudioDescriptionMixLeveldB = -std::numeric_limits<float>::infinity();
+
private:
class MediaMetrics {
public: