VolumeShaper: Enable for offload and direct tracks
Test: Play Music in offload mode
Bug: 31015569
Change-Id: I00bb59e3e6809d4682f42057b1cc083f4fa9b9d1
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index f33c710..f84ba08 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -59,6 +59,10 @@
bool isOffloaded() const
{ return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; }
bool isDirect() const { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
+ bool isOffloadedOrDirect() const { return (mFlags
+ & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
+ | AUDIO_OUTPUT_FLAG_DIRECT)) != 0; }
+
status_t setParameters(const String8& keyValuePairs);
status_t attachAuxEffect(int EffectId);
void setAuxBuffer(int EffectId, int32_t *buffer);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 8bf1688..b10e42c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3063,8 +3063,13 @@
releaseWakeLock_l();
released = true;
}
- ALOGV("wait async completion");
- mWaitWorkCV.wait(mLock);
+
+ const int64_t waitNs = computeWaitTimeNs_l();
+ ALOGV("wait async completion (wait time: %lld)", (long long)waitNs);
+ status_t status = mWaitWorkCV.waitRelative(mLock, waitNs);
+ if (status == TIMED_OUT) {
+ mSignalPending = true; // if timeout recheck everything
+ }
ALOGV("async completion/wake");
if (released) {
acquireWakeLock_l();
@@ -4131,7 +4136,7 @@
// cache the combined master volume and stream type volume for fast mixer; this
// lacks any synchronization or barrier so VolumeProvider may read a stale value
const float vh = track->getVolumeHandler()->getVolume(
- track->mAudioTrackServerProxy->framesReleased());
+ track->mAudioTrackServerProxy->framesReleased()).first;
track->mCachedVolume = masterVolume
* mStreamTypes[track->streamType()].volume
* vh;
@@ -4277,7 +4282,7 @@
vrf = GAIN_FLOAT_UNITY;
}
const float vh = track->getVolumeHandler()->getVolume(
- track->mAudioTrackServerProxy->framesReleased());
+ track->mAudioTrackServerProxy->framesReleased()).first;
// now apply the master volume and stream type volume and shaper volume
vlf *= v * vh;
vrf *= v * vh;
@@ -4756,6 +4761,7 @@
ThreadBase::type_t type, bool systemReady)
: PlaybackThread(audioFlinger, output, id, device, type, systemReady)
// mLeftVolFloat, mRightVolFloat
+ , mVolumeShaperActive(false)
{
}
@@ -4774,13 +4780,12 @@
float v = mMasterVolume * typeVolume;
sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
- if (audio_is_linear_pcm(mFormat) && !usesHwAvSync()) {
- const float vh = track->getVolumeHandler()->getVolume(
+ // Get volumeshaper scaling
+ std::pair<float /* volume */, bool /* active */>
+ vh = track->getVolumeHandler()->getVolume(
track->mAudioTrackServerProxy->framesReleased());
- v *= vh;
- } else {
- // TODO: implement volume scaling in HW
- }
+ v *= vh.first;
+ mVolumeShaperActive = vh.second;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
left = float_from_gain(gain_minifloat_unpack_left(vlr));
@@ -5238,6 +5243,13 @@
mFlushPending = false;
}
+int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
+ // If a VolumeShaper is active, we must wake up periodically to update volume.
+ const int64_t NS_PER_MS = 1000000;
+ return mVolumeShaperActive ?
+ kMinNormalSinkBufferSizeMs * NS_PER_MS : PlaybackThread::computeWaitTimeNs_l();
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 2a6652d..0a17a8e 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -757,6 +757,9 @@
virtual void getAudioPortConfig(struct audio_port_config *config);
+ // Return the asynchronous signal wait time.
+ virtual int64_t computeWaitTimeNs_l() const { return INT64_MAX; }
+
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1174,6 +1177,7 @@
// volumes last sent to audio HAL with stream->set_volume()
float mLeftVolFloat;
float mRightVolFloat;
+ bool mVolumeShaperActive;
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
audio_io_handle_t id, uint32_t device, ThreadBase::type_t type,
@@ -1187,6 +1191,8 @@
public:
virtual bool hasFastMixer() const { return false; }
+
+ virtual int64_t computeWaitTimeNs_l() const override;
};
class OffloadThread : public DirectOutputThread {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index edf41fd..5e07e3b 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -905,10 +905,33 @@
const sp<VolumeShaper::Configuration>& configuration,
const sp<VolumeShaper::Operation>& operation)
{
- // Note: We don't check if Thread exists.
+ sp<VolumeShaper::Configuration> newConfiguration;
- // mVolumeHandler is thread-safe.
- return mVolumeHandler->applyVolumeShaper(configuration, operation);
+ if (isOffloadedOrDirect()) {
+ const VolumeShaper::Configuration::OptionFlag optionFlag
+ = configuration->getOptionFlags();
+ if ((optionFlag & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) == 0) {
+ ALOGW("%s tracks do not support frame counted VolumeShaper,"
+ " using clock time instead", isOffloaded() ? "Offload" : "Direct");
+ newConfiguration = new VolumeShaper::Configuration(*configuration);
+ newConfiguration->setOptionFlags(
+ VolumeShaper::Configuration::OptionFlag(optionFlag
+ | VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME));
+ }
+ }
+
+ VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(
+ (newConfiguration.get() != nullptr ? newConfiguration : configuration), operation);
+
+ if (isOffloadedOrDirect()) {
+ // Signal thread to fetch new volume.
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ thread->broadcast_l();
+ }
+ }
+ return status;
}
sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperState(int id)