Loading include/media/VolumeShaper.h +17 −5 Original line number Diff line number Diff line Loading @@ -528,6 +528,10 @@ public: mDelayXOffset = xOffset; } bool isStarted() const { return mStartFrame >= 0; } std::pair<T /* volume */, bool /* active */> getVolume( int64_t trackFrameCount, double trackSampleRate) { if ((getFlags() & VolumeShaper::Operation::FLAG_DELAY) != 0) { Loading Loading @@ -752,6 +756,8 @@ public: return it->getState(); } // getVolume() is not const, as it updates internal state. // Once called, any VolumeShapers not already started begin running. std::pair<T /* volume */, bool /* active */> getVolume(int64_t trackFrameCount) { AutoMutex _l(mLock); mLastFrame = trackFrameCount; Loading @@ -768,6 +774,14 @@ public: return mLastVolume; } // Used by a client side VolumeHandler to ensure all the VolumeShapers // indicate that they have been started. Upon a change in audioserver // output sink, this information is used for restoration of the server side // VolumeHandler. void setStarted() { (void)getVolume(mLastFrame); // getVolume() will start the individual VolumeShapers. } std::pair<T /* volume */, bool /* active */> getLastVolume() const { AutoMutex _l(mLock); return mLastVolume; Loading @@ -784,14 +798,12 @@ public: return ss.str(); } void forall(const std::function<VolumeShaper::Status ( const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation)> &lambda) { void forall(const std::function<VolumeShaper::Status (const VolumeShaper &)> &lambda) { AutoMutex _l(mLock); VS_LOG("forall: mVolumeShapers.size() %zu", mVolumeShapers.size()); for (const auto &shaper : mVolumeShapers) { VS_LOG("forall applying lambda"); (void)lambda(shaper.mConfiguration, shaper.mOperation); VolumeShaper::Status status = lambda(shaper); VS_LOG("forall applying lambda on shaper (%p): %d", &shaper, (int)status); } } Loading media/libaudioclient/AudioTrack.cpp +32 −9 Original line number Diff line number Diff line Loading @@ -652,6 +652,9 @@ status_t AudioTrack::start() get_sched_policy(0, &mPreviousSchedulingGroup); androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); } // Start our local VolumeHandler for restoration purposes. mVolumeHandler->setStarted(); } else { ALOGE("start() status %d", status); mState = previousState; Loading Loading @@ -2254,17 +2257,20 @@ status_t AudioTrack::restoreTrack_l(const char *from) } } // restore volume handler mVolumeHandler->forall([this](const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation) -> VolumeShaper::Status { sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(*operation); mVolumeHandler->forall([this](const VolumeShaper &shaper) -> VolumeShaper::Status { sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(shaper.mOperation); // TODO: Ideally we would restore to the exact xOffset position // as returned by getVolumeShaperState(), but we don't have that // information when restoring at the client unless we periodically poll // the server or create shared memory state. // // For now, we simply advance to the end of the VolumeShaper effect. // For now, we simply advance to the end of the VolumeShaper effect // if it has been started. if (shaper.isStarted()) { operationToEnd->setXOffset(1.f); return mAudioTrack->applyVolumeShaper(configuration, operationToEnd); } return mAudioTrack->applyVolumeShaper(shaper.mConfiguration, operationToEnd); }); if (mState == STATE_ACTIVE) { Loading Loading @@ -2334,19 +2340,36 @@ VolumeShaper::Status AudioTrack::applyVolumeShaper( AutoMutex lock(mLock); mVolumeHandler->setIdIfNecessary(configuration); VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(configuration, operation); if (status == DEAD_OBJECT) { if (restoreTrack_l("applyVolumeShaper") == OK) { status = mAudioTrack->applyVolumeShaper(configuration, operation); } } if (status >= 0) { // save VolumeShaper for restore mVolumeHandler->applyVolumeShaper(configuration, operation); if (mState == STATE_ACTIVE || mState == STATE_STOPPING) { mVolumeHandler->setStarted(); } } else { // warn only if not an expected restore failure. ALOGW_IF(!((isOffloadedOrDirect_l() || mDoNotReconnect) && status == DEAD_OBJECT), "applyVolumeShaper failed: %d", status); } return status; } sp<VolumeShaper::State> AudioTrack::getVolumeShaperState(int id) { // TODO: To properly restore the AudioTrack // we will need to save the last state in AudioTrackShared. AutoMutex lock(mLock); return mAudioTrack->getVolumeShaperState(id); sp<VolumeShaper::State> state = mAudioTrack->getVolumeShaperState(id); if (state.get() == nullptr && (mCblk->mFlags & CBLK_INVALID) != 0) { if (restoreTrack_l("getVolumeShaperState") == OK) { state = mAudioTrack->getVolumeShaperState(id); } } return state; } status_t AudioTrack::getTimestamp(ExtendedTimestamp *timestamp) Loading media/libmediaplayerservice/MediaPlayerService.cpp +31 −9 Original line number Diff line number Diff line Loading @@ -2029,12 +2029,23 @@ status_t MediaPlayerService::AudioOutput::open( ALOGV("setVolume"); t->setVolume(mLeftVolume, mRightVolume); // Dispatch any queued VolumeShapers when the track was not open. mVolumeHandler->forall([&t](const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation) -> VolumeShaper::Status { return t->applyVolumeShaper(configuration, operation); // Restore VolumeShapers for the MediaPlayer in case the track was recreated // due to an output sink error (e.g. offload to non-offload switch). mVolumeHandler->forall([&t](const VolumeShaper &shaper) -> VolumeShaper::Status { sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(shaper.mOperation); // TODO: Ideally we would restore to the exact xOffset position // as returned by getVolumeShaperState(), but we don't have that // information when restoring at the client unless we periodically poll // the server or create shared memory state. // // For now, we simply advance to the end of the VolumeShaper effect // if it has been started. if (shaper.isStarted()) { operationToEnd->setXOffset(1.f); } return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd); }); mVolumeHandler->reset(); // After dispatching, clear VolumeShaper queue. mSampleRateHz = sampleRate; mFlags = flags; Loading Loading @@ -2075,7 +2086,11 @@ status_t MediaPlayerService::AudioOutput::start() if (mTrack != 0) { mTrack->setVolume(mLeftVolume, mRightVolume); mTrack->setAuxEffectSendLevel(mSendLevel); return mTrack->start(); status_t status = mTrack->start(); if (status == NO_ERROR) { mVolumeHandler->setStarted(); } return status; } return NO_INIT; } Loading Loading @@ -2279,13 +2294,20 @@ VolumeShaper::Status MediaPlayerService::AudioOutput::applyVolumeShaper( Mutex::Autolock lock(mLock); ALOGV("AudioOutput::applyVolumeShaper"); // We take ownership of the VolumeShaper if set before the track is created. mVolumeHandler->setIdIfNecessary(configuration); VolumeShaper::Status status; if (mTrack != 0) { return mTrack->applyVolumeShaper(configuration, operation); status = mTrack->applyVolumeShaper(configuration, operation); if (status >= 0) { (void)mVolumeHandler->applyVolumeShaper(configuration, operation); // TODO: start on exact AudioTrack state (STATE_ACTIVE || STATE_STOPPING) mVolumeHandler->setStarted(); } } else { return mVolumeHandler->applyVolumeShaper(configuration, operation); status = mVolumeHandler->applyVolumeShaper(configuration, operation); } return status; } sp<VolumeShaper::State> MediaPlayerService::AudioOutput::getVolumeShaperState(int id) Loading Loading
include/media/VolumeShaper.h +17 −5 Original line number Diff line number Diff line Loading @@ -528,6 +528,10 @@ public: mDelayXOffset = xOffset; } bool isStarted() const { return mStartFrame >= 0; } std::pair<T /* volume */, bool /* active */> getVolume( int64_t trackFrameCount, double trackSampleRate) { if ((getFlags() & VolumeShaper::Operation::FLAG_DELAY) != 0) { Loading Loading @@ -752,6 +756,8 @@ public: return it->getState(); } // getVolume() is not const, as it updates internal state. // Once called, any VolumeShapers not already started begin running. std::pair<T /* volume */, bool /* active */> getVolume(int64_t trackFrameCount) { AutoMutex _l(mLock); mLastFrame = trackFrameCount; Loading @@ -768,6 +774,14 @@ public: return mLastVolume; } // Used by a client side VolumeHandler to ensure all the VolumeShapers // indicate that they have been started. Upon a change in audioserver // output sink, this information is used for restoration of the server side // VolumeHandler. void setStarted() { (void)getVolume(mLastFrame); // getVolume() will start the individual VolumeShapers. } std::pair<T /* volume */, bool /* active */> getLastVolume() const { AutoMutex _l(mLock); return mLastVolume; Loading @@ -784,14 +798,12 @@ public: return ss.str(); } void forall(const std::function<VolumeShaper::Status ( const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation)> &lambda) { void forall(const std::function<VolumeShaper::Status (const VolumeShaper &)> &lambda) { AutoMutex _l(mLock); VS_LOG("forall: mVolumeShapers.size() %zu", mVolumeShapers.size()); for (const auto &shaper : mVolumeShapers) { VS_LOG("forall applying lambda"); (void)lambda(shaper.mConfiguration, shaper.mOperation); VolumeShaper::Status status = lambda(shaper); VS_LOG("forall applying lambda on shaper (%p): %d", &shaper, (int)status); } } Loading
media/libaudioclient/AudioTrack.cpp +32 −9 Original line number Diff line number Diff line Loading @@ -652,6 +652,9 @@ status_t AudioTrack::start() get_sched_policy(0, &mPreviousSchedulingGroup); androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); } // Start our local VolumeHandler for restoration purposes. mVolumeHandler->setStarted(); } else { ALOGE("start() status %d", status); mState = previousState; Loading Loading @@ -2254,17 +2257,20 @@ status_t AudioTrack::restoreTrack_l(const char *from) } } // restore volume handler mVolumeHandler->forall([this](const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation) -> VolumeShaper::Status { sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(*operation); mVolumeHandler->forall([this](const VolumeShaper &shaper) -> VolumeShaper::Status { sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(shaper.mOperation); // TODO: Ideally we would restore to the exact xOffset position // as returned by getVolumeShaperState(), but we don't have that // information when restoring at the client unless we periodically poll // the server or create shared memory state. // // For now, we simply advance to the end of the VolumeShaper effect. // For now, we simply advance to the end of the VolumeShaper effect // if it has been started. if (shaper.isStarted()) { operationToEnd->setXOffset(1.f); return mAudioTrack->applyVolumeShaper(configuration, operationToEnd); } return mAudioTrack->applyVolumeShaper(shaper.mConfiguration, operationToEnd); }); if (mState == STATE_ACTIVE) { Loading Loading @@ -2334,19 +2340,36 @@ VolumeShaper::Status AudioTrack::applyVolumeShaper( AutoMutex lock(mLock); mVolumeHandler->setIdIfNecessary(configuration); VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(configuration, operation); if (status == DEAD_OBJECT) { if (restoreTrack_l("applyVolumeShaper") == OK) { status = mAudioTrack->applyVolumeShaper(configuration, operation); } } if (status >= 0) { // save VolumeShaper for restore mVolumeHandler->applyVolumeShaper(configuration, operation); if (mState == STATE_ACTIVE || mState == STATE_STOPPING) { mVolumeHandler->setStarted(); } } else { // warn only if not an expected restore failure. ALOGW_IF(!((isOffloadedOrDirect_l() || mDoNotReconnect) && status == DEAD_OBJECT), "applyVolumeShaper failed: %d", status); } return status; } sp<VolumeShaper::State> AudioTrack::getVolumeShaperState(int id) { // TODO: To properly restore the AudioTrack // we will need to save the last state in AudioTrackShared. AutoMutex lock(mLock); return mAudioTrack->getVolumeShaperState(id); sp<VolumeShaper::State> state = mAudioTrack->getVolumeShaperState(id); if (state.get() == nullptr && (mCblk->mFlags & CBLK_INVALID) != 0) { if (restoreTrack_l("getVolumeShaperState") == OK) { state = mAudioTrack->getVolumeShaperState(id); } } return state; } status_t AudioTrack::getTimestamp(ExtendedTimestamp *timestamp) Loading
media/libmediaplayerservice/MediaPlayerService.cpp +31 −9 Original line number Diff line number Diff line Loading @@ -2029,12 +2029,23 @@ status_t MediaPlayerService::AudioOutput::open( ALOGV("setVolume"); t->setVolume(mLeftVolume, mRightVolume); // Dispatch any queued VolumeShapers when the track was not open. mVolumeHandler->forall([&t](const sp<VolumeShaper::Configuration> &configuration, const sp<VolumeShaper::Operation> &operation) -> VolumeShaper::Status { return t->applyVolumeShaper(configuration, operation); // Restore VolumeShapers for the MediaPlayer in case the track was recreated // due to an output sink error (e.g. offload to non-offload switch). mVolumeHandler->forall([&t](const VolumeShaper &shaper) -> VolumeShaper::Status { sp<VolumeShaper::Operation> operationToEnd = new VolumeShaper::Operation(shaper.mOperation); // TODO: Ideally we would restore to the exact xOffset position // as returned by getVolumeShaperState(), but we don't have that // information when restoring at the client unless we periodically poll // the server or create shared memory state. // // For now, we simply advance to the end of the VolumeShaper effect // if it has been started. if (shaper.isStarted()) { operationToEnd->setXOffset(1.f); } return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd); }); mVolumeHandler->reset(); // After dispatching, clear VolumeShaper queue. mSampleRateHz = sampleRate; mFlags = flags; Loading Loading @@ -2075,7 +2086,11 @@ status_t MediaPlayerService::AudioOutput::start() if (mTrack != 0) { mTrack->setVolume(mLeftVolume, mRightVolume); mTrack->setAuxEffectSendLevel(mSendLevel); return mTrack->start(); status_t status = mTrack->start(); if (status == NO_ERROR) { mVolumeHandler->setStarted(); } return status; } return NO_INIT; } Loading Loading @@ -2279,13 +2294,20 @@ VolumeShaper::Status MediaPlayerService::AudioOutput::applyVolumeShaper( Mutex::Autolock lock(mLock); ALOGV("AudioOutput::applyVolumeShaper"); // We take ownership of the VolumeShaper if set before the track is created. mVolumeHandler->setIdIfNecessary(configuration); VolumeShaper::Status status; if (mTrack != 0) { return mTrack->applyVolumeShaper(configuration, operation); status = mTrack->applyVolumeShaper(configuration, operation); if (status >= 0) { (void)mVolumeHandler->applyVolumeShaper(configuration, operation); // TODO: start on exact AudioTrack state (STATE_ACTIVE || STATE_STOPPING) mVolumeHandler->setStarted(); } } else { return mVolumeHandler->applyVolumeShaper(configuration, operation); status = mVolumeHandler->applyVolumeShaper(configuration, operation); } return status; } sp<VolumeShaper::State> MediaPlayerService::AudioOutput::getVolumeShaperState(int id) Loading