diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index df9aea67eb..8607ee1eca 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -2452,13 +2452,8 @@ status_t AudioTrack::setParameters(const String8& keyValuePairs) status_t AudioTrack::selectPresentation(int presentationId, int programId) { AutoMutex lock(mLock); - AudioParameter param = AudioParameter(); - param.addInt(String8(AudioParameter::keyPresentationId), presentationId); - param.addInt(String8(AudioParameter::keyProgramId), programId); - ALOGV("%s(%d): PresentationId/ProgramId[%s]", - __func__, mId, param.toString().string()); - - return mAudioTrack->setParameters(param.toString()); + ALOGV("%s(%d): PresentationId:%d ProgramId:%d", __func__, mId, presentationId, programId); + return mAudioTrack->selectPresentation(presentationId, programId); } VolumeShaper::Status AudioTrack::applyVolumeShaper( diff --git a/media/libaudioclient/IAudioTrack.cpp b/media/libaudioclient/IAudioTrack.cpp index adff05787a..83a568a554 100644 --- a/media/libaudioclient/IAudioTrack.cpp +++ b/media/libaudioclient/IAudioTrack.cpp @@ -39,6 +39,7 @@ enum { PAUSE, ATTACH_AUX_EFFECT, SET_PARAMETERS, + SELECT_PRESENTATION, GET_TIMESTAMP, SIGNAL, APPLY_VOLUME_SHAPER, @@ -127,6 +128,19 @@ public: return status; } + /* Selects the presentation (if available) */ + virtual status_t selectPresentation(int presentationId, int programId) { + Parcel data, reply; + data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); + data.writeInt32(presentationId); + data.writeInt32(programId); + status_t status = remote()->transact(SELECT_PRESENTATION, data, &reply); + if (status == NO_ERROR) { + status = reply.readInt32(); + } + return status; + } + virtual status_t getTimestamp(AudioTimestamp& timestamp) { Parcel data, reply; data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor()); @@ -239,6 +253,11 @@ status_t BnAudioTrack::onTransact( reply->writeInt32(setParameters(keyValuePairs)); return NO_ERROR; } break; + case SELECT_PRESENTATION: { + CHECK_INTERFACE(IAudioTrack, data, reply); + reply->writeInt32(selectPresentation(data.readInt32(), data.readInt32())); + return NO_ERROR; + } break; case GET_TIMESTAMP: { CHECK_INTERFACE(IAudioTrack, data, reply); AudioTimestamp timestamp; diff --git a/media/libaudioclient/include/media/IAudioTrack.h b/media/libaudioclient/include/media/IAudioTrack.h index 94afe3ce66..06e786d294 100644 --- a/media/libaudioclient/include/media/IAudioTrack.h +++ b/media/libaudioclient/include/media/IAudioTrack.h @@ -70,6 +70,9 @@ public: /* Send parameters to the audio hardware */ virtual status_t setParameters(const String8& keyValuePairs) = 0; + /* Selects the presentation (if available) */ + virtual status_t selectPresentation(int presentationId, int programId) = 0; + /* Return NO_ERROR if timestamp is valid. timestamp is undefined otherwise. */ virtual status_t getTimestamp(AudioTimestamp& timestamp) = 0; diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp index bfa80e8c71..5ac2d9af08 100644 --- a/media/libaudiohal/impl/StreamHalHidl.cpp +++ b/media/libaudiohal/impl/StreamHalHidl.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -347,6 +348,24 @@ status_t StreamOutHalHidl::setVolume(float left, float right) { return processReturn("setVolume", mStream->setVolume(left, right)); } +#if MAJOR_VERSION == 2 +status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) { + if (mStream == 0) return NO_INIT; + std::vector parameters; + String8 halParameters; + parameters.push_back({AudioParameter::keyPresentationId, std::to_string(presentationId)}); + parameters.push_back({AudioParameter::keyProgramId, std::to_string(programId)}); + parametersToHal(hidl_vec(parameters), &halParameters); + return setParameters(halParameters); +} +#elif MAJOR_VERSION == 4 +status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) { + if (mStream == 0) return NO_INIT; + return processReturn("selectPresentation", + mStream->selectPresentation(presentationId, programId)); +} +#endif + status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) { if (mStream == 0) return NO_INIT; *written = 0; diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h index 95ec7f1d17..74101d7964 100644 --- a/media/libaudiohal/impl/StreamHalHidl.h +++ b/media/libaudiohal/impl/StreamHalHidl.h @@ -131,6 +131,9 @@ class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl { // Use this method in situations where audio mixing is done in the hardware. virtual status_t setVolume(float left, float right); + // Selects the audio presentation (if available). + virtual status_t selectPresentation(int presentationId, int programId); + // Write audio buffer to driver. virtual status_t write(const void *buffer, size_t bytes, size_t *written); diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp index b134f5797c..0aba7c119b 100644 --- a/media/libaudiohal/impl/StreamHalLocal.cpp +++ b/media/libaudiohal/impl/StreamHalLocal.cpp @@ -18,6 +18,7 @@ //#define LOG_NDEBUG 0 #include +#include #include #include "DeviceHalLocal.h" @@ -138,6 +139,13 @@ status_t StreamOutHalLocal::setVolume(float left, float right) { return mStream->set_volume(mStream, left, right); } +status_t StreamOutHalLocal::selectPresentation(int presentationId, int programId) { + AudioParameter param; + param.addInt(String8(AudioParameter::keyPresentationId), presentationId); + param.addInt(String8(AudioParameter::keyProgramId), programId); + return setParameters(param.toString()); +} + status_t StreamOutHalLocal::write(const void *buffer, size_t bytes, size_t *written) { ssize_t writeResult = mStream->write(mStream, buffer, bytes); if (writeResult > 0) { diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h index cea4229aa0..4fd1960887 100644 --- a/media/libaudiohal/impl/StreamHalLocal.h +++ b/media/libaudiohal/impl/StreamHalLocal.h @@ -103,6 +103,9 @@ class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal { // Use this method in situations where audio mixing is done in the hardware. virtual status_t setVolume(float left, float right); + // Selects the audio presentation (if available). + virtual status_t selectPresentation(int presentationId, int programId); + // Write audio buffer to driver. virtual status_t write(const void *buffer, size_t bytes, size_t *written); diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h index c969e2853c..bd71dc0986 100644 --- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h +++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h @@ -109,6 +109,9 @@ class StreamOutHalInterface : public virtual StreamHalInterface { // Use this method in situations where audio mixing is done in the hardware. virtual status_t setVolume(float left, float right) = 0; + // Selects the audio presentation (if available). + virtual status_t selectPresentation(int presentationId, int programId) = 0; + // Write audio buffer to driver. virtual status_t write(const void *buffer, size_t bytes, size_t *written) = 0; diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index b6b381593b..1b20693d31 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -553,6 +553,7 @@ using effect_buffer_t = int16_t; virtual void pause(); virtual status_t attachAuxEffect(int effectId); virtual status_t setParameters(const String8& keyValuePairs); + virtual status_t selectPresentation(int presentationId, int programId); virtual media::VolumeShaper::Status applyVolumeShaper( const sp& configuration, const sp& operation) override; diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 53ea9a43b0..971f6a5077 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -67,6 +67,7 @@ public: bool isStatic() const { return mSharedBuffer.get() != nullptr; } status_t setParameters(const String8& keyValuePairs); + status_t selectPresentation(int presentationId, int programId); status_t attachAuxEffect(int EffectId); void setAuxBuffer(int EffectId, int32_t *buffer); int32_t *auxBuffer() const { return mAuxBuffer; } diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index f833cf7bf2..cec08196ee 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2413,6 +2413,14 @@ String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) return String8(); } +status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) { + Mutex::Autolock _l(mLock); + if (mOutput == nullptr || mOutput->stream == nullptr) { + return NO_INIT; + } + return mOutput->stream->selectPresentation(presentationId, programId); +} + void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event, pid_t pid) { sp desc = new AudioIoDescriptor(); ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event); diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 49fc2345f1..7f3ea0f4e7 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -1199,6 +1199,8 @@ public: audio_io_handle_t id, audio_devices_t device, bool systemReady); virtual ~DirectOutputThread(); + status_t selectPresentation(int presentationId, int programId); + // Thread virtuals virtual bool checkForNewParameter_l(const String8& keyValuePair, diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index f2617ae730..91a3286892 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -326,6 +326,10 @@ status_t AudioFlinger::TrackHandle::setParameters(const String8& keyValuePairs) return mTrack->setParameters(keyValuePairs); } +status_t AudioFlinger::TrackHandle::selectPresentation(int presentationId, int programId) { + return mTrack->selectPresentation(presentationId, programId); +} + VolumeShaper::Status AudioFlinger::TrackHandle::applyVolumeShaper( const sp& configuration, const sp& operation) { @@ -976,6 +980,19 @@ status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyVa } } +status_t AudioFlinger::PlaybackThread::Track::selectPresentation(int presentationId, + int programId) { + sp thread = mThread.promote(); + if (thread == 0) { + ALOGE("thread is dead"); + return FAILED_TRANSACTION; + } else if ((thread->type() == ThreadBase::DIRECT) || (thread->type() == ThreadBase::OFFLOAD)) { + DirectOutputThread *directOutputThread = static_cast(thread.get()); + return directOutputThread->selectPresentation(presentationId, programId); + } + return INVALID_OPERATION; +} + VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper( const sp& configuration, const sp& operation)