Add selectPresentation API to IAudioTrack
The Java AudioTrack interface has a setPresentation API. This
calls the setParameters API in IAudioTrack. However, this does
not eventuate into a call into the android.hardware.audio@4.0
IStreamOut selectPresentation API.
Add selectPresentation API to IAudioTrack and call down to the
android.hardware.audio@4.0 IStreamOut selectPresentation API.
Translate into calls to setParameters API for legacy HAL
interfaces.
Bug: 63901775
Test: compile
Change-Id: Id634a107f3f93ab18dc80d2bd0af67bda35e859f
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index df9aea6..8607ee1 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2452,13 +2452,8 @@
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 adff057..83a568a 100644
--- a/media/libaudioclient/IAudioTrack.cpp
+++ b/media/libaudioclient/IAudioTrack.cpp
@@ -39,6 +39,7 @@
PAUSE,
ATTACH_AUX_EFFECT,
SET_PARAMETERS,
+ SELECT_PRESENTATION,
GET_TIMESTAMP,
SIGNAL,
APPLY_VOLUME_SHAPER,
@@ -127,6 +128,19 @@
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 @@
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 94afe3c..06e786d 100644
--- a/media/libaudioclient/include/media/IAudioTrack.h
+++ b/media/libaudioclient/include/media/IAudioTrack.h
@@ -70,6 +70,9 @@
/* 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 bfa80e8..5ac2d9a 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -20,6 +20,7 @@
#include <android/hardware/audio/2.0/IStreamOutCallback.h>
#include <android/hardware/audio/4.0/IStreamOutCallback.h>
#include <hwbinder/IPCThreadState.h>
+#include <media/AudioParameter.h>
#include <mediautils/SchedulingPolicyService.h>
#include <utils/Log.h>
@@ -347,6 +348,24 @@
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<ParameterValue> parameters;
+ String8 halParameters;
+ parameters.push_back({AudioParameter::keyPresentationId, std::to_string(presentationId)});
+ parameters.push_back({AudioParameter::keyProgramId, std::to_string(programId)});
+ parametersToHal(hidl_vec<ParameterValue>(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 95ec7f1..74101d7 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -131,6 +131,9 @@
// 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 b134f57..0aba7c1 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -18,6 +18,7 @@
//#define LOG_NDEBUG 0
#include <hardware/audio.h>
+#include <media/AudioParameter.h>
#include <utils/Log.h>
#include "DeviceHalLocal.h"
@@ -138,6 +139,13 @@
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 cea4229..4fd1960 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -103,6 +103,9 @@
// 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 c969e28..bd71dc0 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -109,6 +109,9 @@
// 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 b6b3815..1b20693 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -553,6 +553,7 @@
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<media::VolumeShaper::Configuration>& configuration,
const sp<media::VolumeShaper::Operation>& operation) override;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 53ea9a4..971f6a5 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -67,6 +67,7 @@
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 f833cf7..cec0819 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2413,6 +2413,14 @@
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<AudioIoDescriptor> 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 49fc234..7f3ea0f 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1199,6 +1199,8 @@
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 f2617ae..91a3286 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -326,6 +326,10 @@
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<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation) {
@@ -976,6 +980,19 @@
}
}
+status_t AudioFlinger::PlaybackThread::Track::selectPresentation(int presentationId,
+ int programId) {
+ sp<ThreadBase> 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<DirectOutputThread*>(thread.get());
+ return directOutputThread->selectPresentation(presentationId, programId);
+ }
+ return INVALID_OPERATION;
+}
+
VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper(
const sp<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation)