Loading include/media/VolumeShaper.h +51 −44 Original line number Diff line number Diff line Loading @@ -94,6 +94,14 @@ public: , mId(-1) { } Configuration(const Configuration &configuration) : Interpolator<S, T>(*static_cast<const Interpolator<S, T> *>(&configuration)) , mType(configuration.mType) , mOptionFlags(configuration.mOptionFlags) , mDurationMs(configuration.mDurationMs) , mId(configuration.mId) { } Type getType() const { return mType; } Loading Loading @@ -493,13 +501,8 @@ public: return new VolumeShaper::State(mLastVolume, mXOffset); } std::pair<T, bool> getVolume(int64_t trackFrameCount, double trackSampleRate) { if (mConfiguration.get() == nullptr || mConfiguration->empty()) { ALOGE("nonexistent VolumeShaper, removing"); mLastVolume = T(1); mXOffset = 0.f; return std::make_pair(T(1), true); } std::pair<T /* volume */, bool /* active */> getVolume( int64_t trackFrameCount, double trackSampleRate) { if ((getFlags() & VolumeShaper::Operation::FLAG_DELAY) != 0) { VS_LOG("delayed VolumeShaper, ignoring"); mLastVolume = T(1); Loading Loading @@ -534,13 +537,13 @@ public: if (x > mConfiguration->last().first) { mXOffset = 0.f; mLastVolume = 1.f; return std::make_pair(T(1), false); // too early return std::make_pair(T(1), true); // too early } } else { if (x < mConfiguration->first().first) { mXOffset = 0.f; mLastVolume = 1.f; return std::make_pair(T(1), false); // too early return std::make_pair(T(1), true); // too early } if (x > mConfiguration->last().first) { mXOffset = 1.f; Loading @@ -558,7 +561,7 @@ public: const T volume = mConfiguration->adjustVolume(volumeChange); VS_LOG("volume: %f unscaled: %f", volume, unscaledVolume); mLastVolume = volume; return std::make_pair(volume, false); return std::make_pair(volume, true); } std::string toString() const { Loading Loading @@ -597,6 +600,8 @@ public: VolumeShaper::Status applyVolumeShaper( const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation) { VS_LOG("applyVolumeShaper:configuration: %s", configuration->toString().c_str()); VS_LOG("applyVolumeShaper:operation: %s", operation->toString().c_str()); AutoMutex _l(mLock); if (configuration == nullptr) { ALOGE("null configuration"); Loading @@ -614,34 +619,6 @@ public: VS_LOG("applyVolumeShaper id: %d", id); switch (configuration->getType()) { case VolumeShaper::Configuration::TYPE_ID: { VS_LOG("trying to find id: %d", id); auto it = findId_l(id); if (it == mVolumeShapers.end()) { VS_LOG("couldn't find id: %d\n%s", id, this->toString().c_str()); return VolumeShaper::Status(INVALID_OPERATION); } if ((it->getFlags() & VolumeShaper::Operation::FLAG_TERMINATE) != 0) { VS_LOG("terminate id: %d", id); mVolumeShapers.erase(it); break; } if ((it->getFlags() & VolumeShaper::Operation::FLAG_REVERSE) != (operation->getFlags() & VolumeShaper::Operation::FLAG_REVERSE)) { const S x = it->mXTranslate((T)mLastFrame); VS_LOG("translation: %f", x); // reflect position S target = 1.f - x; if (target < it->mConfiguration->first().first) { VS_LOG("clamp to start - begin immediately"); target = 0.; } VS_LOG("target: %f", target); it->mXTranslate.setOffset(it->mXTranslate.getOffset() + (x - target) / it->mXTranslate.getScale()); } it->mOperation = operation; // replace the operation } break; case VolumeShaper::Configuration::TYPE_SCALE: { const int replaceId = operation->getReplaceId(); if (replaceId >= 0) { Loading Loading @@ -670,6 +647,38 @@ public: } // create new VolumeShaper mVolumeShapers.emplace_back(configuration, operation); } // fall through to handle the operation case VolumeShaper::Configuration::TYPE_ID: { VS_LOG("trying to find id: %d", id); auto it = findId_l(id); if (it == mVolumeShapers.end()) { VS_LOG("couldn't find id: %d", id); return VolumeShaper::Status(INVALID_OPERATION); } if ((it->getFlags() & VolumeShaper::Operation::FLAG_TERMINATE) != 0) { VS_LOG("terminate id: %d", id); mVolumeShapers.erase(it); break; } const bool clockTime = (it->mConfiguration->getOptionFlags() & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) != 0; if ((it->getFlags() & VolumeShaper::Operation::FLAG_REVERSE) != (operation->getFlags() & VolumeShaper::Operation::FLAG_REVERSE)) { const int64_t frameCount = clockTime ? VolumeShaper::getNowUs() : mLastFrame; const S x = it->mXTranslate((T)frameCount); VS_LOG("reverse translation: %f", x); // reflect position S target = 1.f - x; if (target < it->mConfiguration->first().first) { VS_LOG("clamp to start - begin immediately"); target = 0.; } VS_LOG("target reverse: %f", target); it->mXTranslate.setOffset(it->mXTranslate.getOffset() + (x - target) / it->mXTranslate.getScale()); } it->mOperation = operation; // replace the operation } break; } return VolumeShaper::Status(id); Loading @@ -684,21 +693,19 @@ public: return it->getState(); } T getVolume(int64_t trackFrameCount) { std::pair<T /* volume */, bool /* active */> getVolume(int64_t trackFrameCount) { AutoMutex _l(mLock); mLastFrame = trackFrameCount; T volume(1); size_t activeCount = 0; for (auto it = mVolumeShapers.begin(); it != mVolumeShapers.end();) { std::pair<T, bool> shaperVolume = it->getVolume(trackFrameCount, mSampleRate); volume *= shaperVolume.first; if (shaperVolume.second) { it = mVolumeShapers.erase(it); continue; } activeCount += shaperVolume.second; ++it; } return volume; return std::make_pair(volume, activeCount != 0); } std::string toString() const { Loading services/audioflinger/PlaybackTracks.h +4 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ public: 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); Loading services/audioflinger/Threads.cpp +22 −10 Original line number Diff line number Diff line Loading @@ -3063,8 +3063,13 @@ bool AudioFlinger::PlaybackThread::threadLoop() 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(); Loading Loading @@ -4131,7 +4136,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // 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; Loading Loading @@ -4277,7 +4282,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac 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; Loading Loading @@ -4756,6 +4761,7 @@ AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& aud ThreadBase::type_t type, bool systemReady) : PlaybackThread(audioFlinger, output, id, device, type, systemReady) // mLeftVolFloat, mRightVolFloat , mVolumeShaperActive(false) { } Loading @@ -4774,13 +4780,12 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr 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)); Loading Loading @@ -5238,6 +5243,13 @@ void AudioFlinger::DirectOutputThread::flushHw_l() 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( Loading services/audioflinger/Threads.h +6 −0 Original line number Diff line number Diff line Loading @@ -757,6 +757,9 @@ public: 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 Loading Loading @@ -1174,6 +1177,7 @@ protected: // 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, Loading @@ -1187,6 +1191,8 @@ protected: public: virtual bool hasFastMixer() const { return false; } virtual int64_t computeWaitTimeNs_l() const override; }; class OffloadThread : public DirectOutputThread { Loading services/audioflinger/Tracks.cpp +26 −3 Original line number Diff line number Diff line Loading @@ -905,10 +905,33 @@ VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper( const sp<VolumeShaper::Configuration>& configuration, const sp<VolumeShaper::Operation>& operation) { // Note: We don't check if Thread exists. sp<VolumeShaper::Configuration> newConfiguration; 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); // mVolumeHandler is thread-safe. return mVolumeHandler->applyVolumeShaper(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) Loading Loading
include/media/VolumeShaper.h +51 −44 Original line number Diff line number Diff line Loading @@ -94,6 +94,14 @@ public: , mId(-1) { } Configuration(const Configuration &configuration) : Interpolator<S, T>(*static_cast<const Interpolator<S, T> *>(&configuration)) , mType(configuration.mType) , mOptionFlags(configuration.mOptionFlags) , mDurationMs(configuration.mDurationMs) , mId(configuration.mId) { } Type getType() const { return mType; } Loading Loading @@ -493,13 +501,8 @@ public: return new VolumeShaper::State(mLastVolume, mXOffset); } std::pair<T, bool> getVolume(int64_t trackFrameCount, double trackSampleRate) { if (mConfiguration.get() == nullptr || mConfiguration->empty()) { ALOGE("nonexistent VolumeShaper, removing"); mLastVolume = T(1); mXOffset = 0.f; return std::make_pair(T(1), true); } std::pair<T /* volume */, bool /* active */> getVolume( int64_t trackFrameCount, double trackSampleRate) { if ((getFlags() & VolumeShaper::Operation::FLAG_DELAY) != 0) { VS_LOG("delayed VolumeShaper, ignoring"); mLastVolume = T(1); Loading Loading @@ -534,13 +537,13 @@ public: if (x > mConfiguration->last().first) { mXOffset = 0.f; mLastVolume = 1.f; return std::make_pair(T(1), false); // too early return std::make_pair(T(1), true); // too early } } else { if (x < mConfiguration->first().first) { mXOffset = 0.f; mLastVolume = 1.f; return std::make_pair(T(1), false); // too early return std::make_pair(T(1), true); // too early } if (x > mConfiguration->last().first) { mXOffset = 1.f; Loading @@ -558,7 +561,7 @@ public: const T volume = mConfiguration->adjustVolume(volumeChange); VS_LOG("volume: %f unscaled: %f", volume, unscaledVolume); mLastVolume = volume; return std::make_pair(volume, false); return std::make_pair(volume, true); } std::string toString() const { Loading Loading @@ -597,6 +600,8 @@ public: VolumeShaper::Status applyVolumeShaper( const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation) { VS_LOG("applyVolumeShaper:configuration: %s", configuration->toString().c_str()); VS_LOG("applyVolumeShaper:operation: %s", operation->toString().c_str()); AutoMutex _l(mLock); if (configuration == nullptr) { ALOGE("null configuration"); Loading @@ -614,34 +619,6 @@ public: VS_LOG("applyVolumeShaper id: %d", id); switch (configuration->getType()) { case VolumeShaper::Configuration::TYPE_ID: { VS_LOG("trying to find id: %d", id); auto it = findId_l(id); if (it == mVolumeShapers.end()) { VS_LOG("couldn't find id: %d\n%s", id, this->toString().c_str()); return VolumeShaper::Status(INVALID_OPERATION); } if ((it->getFlags() & VolumeShaper::Operation::FLAG_TERMINATE) != 0) { VS_LOG("terminate id: %d", id); mVolumeShapers.erase(it); break; } if ((it->getFlags() & VolumeShaper::Operation::FLAG_REVERSE) != (operation->getFlags() & VolumeShaper::Operation::FLAG_REVERSE)) { const S x = it->mXTranslate((T)mLastFrame); VS_LOG("translation: %f", x); // reflect position S target = 1.f - x; if (target < it->mConfiguration->first().first) { VS_LOG("clamp to start - begin immediately"); target = 0.; } VS_LOG("target: %f", target); it->mXTranslate.setOffset(it->mXTranslate.getOffset() + (x - target) / it->mXTranslate.getScale()); } it->mOperation = operation; // replace the operation } break; case VolumeShaper::Configuration::TYPE_SCALE: { const int replaceId = operation->getReplaceId(); if (replaceId >= 0) { Loading Loading @@ -670,6 +647,38 @@ public: } // create new VolumeShaper mVolumeShapers.emplace_back(configuration, operation); } // fall through to handle the operation case VolumeShaper::Configuration::TYPE_ID: { VS_LOG("trying to find id: %d", id); auto it = findId_l(id); if (it == mVolumeShapers.end()) { VS_LOG("couldn't find id: %d", id); return VolumeShaper::Status(INVALID_OPERATION); } if ((it->getFlags() & VolumeShaper::Operation::FLAG_TERMINATE) != 0) { VS_LOG("terminate id: %d", id); mVolumeShapers.erase(it); break; } const bool clockTime = (it->mConfiguration->getOptionFlags() & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) != 0; if ((it->getFlags() & VolumeShaper::Operation::FLAG_REVERSE) != (operation->getFlags() & VolumeShaper::Operation::FLAG_REVERSE)) { const int64_t frameCount = clockTime ? VolumeShaper::getNowUs() : mLastFrame; const S x = it->mXTranslate((T)frameCount); VS_LOG("reverse translation: %f", x); // reflect position S target = 1.f - x; if (target < it->mConfiguration->first().first) { VS_LOG("clamp to start - begin immediately"); target = 0.; } VS_LOG("target reverse: %f", target); it->mXTranslate.setOffset(it->mXTranslate.getOffset() + (x - target) / it->mXTranslate.getScale()); } it->mOperation = operation; // replace the operation } break; } return VolumeShaper::Status(id); Loading @@ -684,21 +693,19 @@ public: return it->getState(); } T getVolume(int64_t trackFrameCount) { std::pair<T /* volume */, bool /* active */> getVolume(int64_t trackFrameCount) { AutoMutex _l(mLock); mLastFrame = trackFrameCount; T volume(1); size_t activeCount = 0; for (auto it = mVolumeShapers.begin(); it != mVolumeShapers.end();) { std::pair<T, bool> shaperVolume = it->getVolume(trackFrameCount, mSampleRate); volume *= shaperVolume.first; if (shaperVolume.second) { it = mVolumeShapers.erase(it); continue; } activeCount += shaperVolume.second; ++it; } return volume; return std::make_pair(volume, activeCount != 0); } std::string toString() const { Loading
services/audioflinger/PlaybackTracks.h +4 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ public: 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); Loading
services/audioflinger/Threads.cpp +22 −10 Original line number Diff line number Diff line Loading @@ -3063,8 +3063,13 @@ bool AudioFlinger::PlaybackThread::threadLoop() 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(); Loading Loading @@ -4131,7 +4136,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // 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; Loading Loading @@ -4277,7 +4282,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac 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; Loading Loading @@ -4756,6 +4761,7 @@ AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& aud ThreadBase::type_t type, bool systemReady) : PlaybackThread(audioFlinger, output, id, device, type, systemReady) // mLeftVolFloat, mRightVolFloat , mVolumeShaperActive(false) { } Loading @@ -4774,13 +4780,12 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr 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)); Loading Loading @@ -5238,6 +5243,13 @@ void AudioFlinger::DirectOutputThread::flushHw_l() 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( Loading
services/audioflinger/Threads.h +6 −0 Original line number Diff line number Diff line Loading @@ -757,6 +757,9 @@ public: 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 Loading Loading @@ -1174,6 +1177,7 @@ protected: // 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, Loading @@ -1187,6 +1191,8 @@ protected: public: virtual bool hasFastMixer() const { return false; } virtual int64_t computeWaitTimeNs_l() const override; }; class OffloadThread : public DirectOutputThread { Loading
services/audioflinger/Tracks.cpp +26 −3 Original line number Diff line number Diff line Loading @@ -905,10 +905,33 @@ VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper( const sp<VolumeShaper::Configuration>& configuration, const sp<VolumeShaper::Operation>& operation) { // Note: We don't check if Thread exists. sp<VolumeShaper::Configuration> newConfiguration; 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); // mVolumeHandler is thread-safe. return mVolumeHandler->applyVolumeShaper(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) Loading