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
Merged-In: Idb22ce6714fa240b2b4b3b8637b16d3a51228fa1
Change-Id: Idb22ce6714fa240b2b4b3b8637b16d3a51228fa1
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 2c40fbb..19d1d1a 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1075,6 +1075,40 @@
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)
+{
+ return mAudioTrack->setDualMonoMode(mode);
+}
+
+status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
+{
+ AutoMutex lock(mLock);
+ return mAudioTrack->getDualMonoMode(mode);
+}
+
+status_t AudioTrack::setAudioDescriptionMixLevel(float leveldB)
+{
+ AutoMutex lock(mLock);
+ return setAudioDescriptionMixLevel_l(leveldB);
+}
+
+status_t AudioTrack::setAudioDescriptionMixLevel_l(float leveldB)
+{
+ return mAudioTrack->setAudioDescriptionMixLevel(leveldB);
+}
+
+status_t AudioTrack::getAudioDescriptionMixLevel(float* leveldB) const
+{
+ AutoMutex lock(mLock);
+ return mAudioTrack->getAudioDescriptionMixLevel(leveldB);
+}
+
status_t AudioTrack::setPlaybackRate(const AudioPlaybackRate &playbackRate)
{
AutoMutex lock(mLock);
@@ -1082,7 +1116,11 @@
return NO_ERROR;
}
if (isOffloadedOrDirect_l()) {
- return INVALID_OPERATION;
+ status_t status = mAudioTrack->setPlaybackRateParameters(playbackRate);
+ if (status == NO_ERROR) {
+ mPlaybackRate = playbackRate;
+ }
+ return status;
}
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
return INVALID_OPERATION;
@@ -1147,9 +1185,16 @@
return NO_ERROR;
}
-const AudioPlaybackRate& AudioTrack::getPlaybackRate() const
+const AudioPlaybackRate& AudioTrack::getPlaybackRate()
{
AutoMutex lock(mLock);
+ if (isOffloadedOrDirect_l()) {
+ audio_playback_rate_t playbackRateTemp;
+ const status_t status = mAudioTrack->getPlaybackRateParameters(&playbackRateTemp);
+ if (status == NO_ERROR) { // update local version if changed.
+ mPlaybackRate = playbackRateTemp;
+ }
+ }
return mPlaybackRate;
}
@@ -1745,6 +1790,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/IAudioTrack.cpp b/media/libaudioclient/IAudioTrack.cpp
index 6219e7a..6fcf300 100644
--- a/media/libaudioclient/IAudioTrack.cpp
+++ b/media/libaudioclient/IAudioTrack.cpp
@@ -44,6 +44,12 @@
SIGNAL,
APPLY_VOLUME_SHAPER,
GET_VOLUME_SHAPER_STATE,
+ SET_DUAL_MONO_MODE,
+ GET_DUAL_MONO_MODE,
+ SET_AUDIO_DESCRIPTION_MIX_LEVEL,
+ GET_AUDIO_DESCRIPTION_MIX_LEVEL,
+ SET_PLAYBACK_RATE_PARAMETERS,
+ GET_PLAYBACK_RATE_PARAMETERS,
};
class BpAudioTrack : public BpInterface<IAudioTrack>
@@ -207,6 +213,92 @@
}
return state;
}
+
+ status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_DUAL_MONO_MODE, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ *mode = (audio_dual_mono_mode_t)reply.readInt32();
+ return NO_ERROR;
+ }
+
+ status_t setDualMonoMode(audio_dual_mono_mode_t mode) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32((int32_t)mode);
+ status_t status = remote()->transact(SET_DUAL_MONO_MODE, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readInt32();
+ }
+
+ status_t getAudioDescriptionMixLevel(float* leveldB) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_AUDIO_DESCRIPTION_MIX_LEVEL, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ *leveldB = reply.readFloat();
+ return NO_ERROR;
+ }
+
+ status_t setAudioDescriptionMixLevel(float leveldB) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeFloat(leveldB);
+ status_t status = remote()->transact(SET_AUDIO_DESCRIPTION_MIX_LEVEL, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readInt32();
+ }
+
+ status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_PLAYBACK_RATE_PARAMETERS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ playbackRate->mSpeed = reply.readFloat();
+ playbackRate->mPitch = reply.readFloat();
+ playbackRate->mStretchMode =
+ static_cast<audio_timestretch_stretch_mode_t>(reply.readInt32());
+ playbackRate->mFallbackMode =
+ static_cast<audio_timestretch_fallback_mode_t>(reply.readInt32());
+ return NO_ERROR;
+ }
+
+ status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeFloat(playbackRate.mSpeed);
+ data.writeFloat(playbackRate.mPitch);
+ data.writeInt32(playbackRate.mStretchMode);
+ data.writeInt32(playbackRate.mFallbackMode);
+ status_t status = remote()->transact(SET_PLAYBACK_RATE_PARAMETERS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
@@ -309,6 +401,59 @@
}
return NO_ERROR;
} break;
+ case SET_DUAL_MONO_MODE: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32( setDualMonoMode((audio_dual_mono_mode_t)data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case GET_DUAL_MONO_MODE: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ audio_dual_mono_mode_t mode;
+ const status_t status = getDualMonoMode(&mode);
+ reply->writeInt32((int32_t)status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(mode);
+ }
+ return NO_ERROR;
+ } break;
+ case SET_AUDIO_DESCRIPTION_MIX_LEVEL: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32( setAudioDescriptionMixLevel(data.readFloat()) );
+ return NO_ERROR;
+ } break;
+ case GET_AUDIO_DESCRIPTION_MIX_LEVEL: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ float f;
+ const status_t status = getAudioDescriptionMixLevel(&f);
+ reply->writeInt32((int32_t)status);
+ if (status == NO_ERROR) {
+ reply->writeFloat(f);
+ }
+ return NO_ERROR;
+ } break;
+ case SET_PLAYBACK_RATE_PARAMETERS: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ audio_playback_rate_t playbackRate = {
+ data.readFloat(),
+ data.readFloat(),
+ static_cast<audio_timestretch_stretch_mode_t>(data.readInt32()),
+ static_cast<audio_timestretch_fallback_mode_t>(data.readInt32())};
+ reply->writeInt32( setPlaybackRateParameters(playbackRate) );
+ return NO_ERROR;
+ } break;
+ case GET_PLAYBACK_RATE_PARAMETERS: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ audio_playback_rate_t playbackRate;
+ const status_t status = getPlaybackRateParameters(&playbackRate);
+ reply->writeInt32((int32_t)status);
+ if (status == NO_ERROR) {
+ reply->writeFloat(playbackRate.mSpeed);
+ reply->writeFloat(playbackRate.mPitch);
+ reply->writeInt32(playbackRate.mStretchMode);
+ reply->writeInt32(playbackRate.mFallbackMode);
+ }
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index de183d8..fac4c83 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -513,6 +513,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
@@ -526,7 +538,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.
@@ -1070,6 +1082,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<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
@@ -1282,6 +1300,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:
diff --git a/media/libaudioclient/include/media/IAudioTrack.h b/media/libaudioclient/include/media/IAudioTrack.h
index 06e786d..dbbbf35 100644
--- a/media/libaudioclient/include/media/IAudioTrack.h
+++ b/media/libaudioclient/include/media/IAudioTrack.h
@@ -27,6 +27,7 @@
#include <utils/String8.h>
#include <media/AudioTimestamp.h>
#include <media/VolumeShaper.h>
+#include <system/audio.h>
namespace android {
@@ -86,6 +87,24 @@
/* gets the volume shaper state */
virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) = 0;
+
+ /* Returns the Dual Mono mode presentation setting. */
+ virtual status_t getDualMonoMode(audio_dual_mono_mode_t* mode) = 0;
+
+ /* Sets the Dual Mono mode presentation on the output device. */
+ virtual status_t setDualMonoMode(audio_dual_mono_mode_t mode) = 0;
+
+ /* Returns the Audio Description Mix level in dB. */
+ virtual status_t getAudioDescriptionMixLevel(float* leveldB) = 0;
+
+ /* Sets the Audio Description Mix level in dB. */
+ virtual status_t setAudioDescriptionMixLevel(float leveldB) = 0;
+
+ /* Retrieves current playback rate parameters. */
+ virtual status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) = 0;
+
+ /* Sets the playback rate parameters that control playback behavior. */
+ virtual status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) = 0;
};
// ----------------------------------------------------------------------------