Loading services/audioflinger/Threads.cpp +121 −70 Original line number Diff line number Diff line Loading @@ -508,7 +508,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), // mName will be set by concrete (non-virtual) subclass mDeathRecipient(new PMDeathRecipient(this)), mSystemReady(systemReady) mSystemReady(systemReady), mNotifiedBatteryStart(false) { memset(&mPatch, 0, sizeof(struct audio_patch)); } Loading Loading @@ -849,10 +850,10 @@ void AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& } } void AudioFlinger::ThreadBase::acquireWakeLock() void AudioFlinger::ThreadBase::acquireWakeLock(int uid) { Mutex::Autolock _l(mLock); acquireWakeLock_l(); acquireWakeLock_l(uid); } String16 AudioFlinger::ThreadBase::getWakeLockTag() Loading @@ -874,23 +875,37 @@ String16 AudioFlinger::ThreadBase::getWakeLockTag() } } void AudioFlinger::ThreadBase::acquireWakeLock_l() void AudioFlinger::ThreadBase::acquireWakeLock_l(int uid) { getPowerManager_l(); if (mPowerManager != 0) { sp<IBinder> binder = new BBinder(); // Uses AID_AUDIOSERVER for wakelock. updateWakeLockUids_l() updates with client uids. status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, status_t status; if (uid >= 0) { status = mPowerManager->acquireWakeLockWithUid(POWERMANAGER_PARTIAL_WAKE_LOCK, binder, getWakeLockTag(), String16("audioserver"), uid, true /* FIXME force oneway contrary to .aidl */); } else { status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, binder, getWakeLockTag(), String16("audioserver"), true /* FIXME force oneway contrary to .aidl */); } if (status == NO_ERROR) { mWakeLockToken = binder; } ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status); } if (!mNotifiedBatteryStart) { // TODO: call this function for each track when it becomes active. BatteryNotifier::getInstance().noteStartAudio(AID_AUDIOSERVER); mNotifiedBatteryStart = true; } gBoottime.acquire(mWakeLockToken); mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] = gBoottime.getBoottimeOffset(); Loading @@ -913,6 +928,12 @@ void AudioFlinger::ThreadBase::releaseWakeLock_l() } mWakeLockToken.clear(); } if (mNotifiedBatteryStart) { // TODO: call this function for each track when it becomes inactive. BatteryNotifier::getInstance().noteStopAudio(AID_AUDIOSERVER); mNotifiedBatteryStart = false; } } void AudioFlinger::ThreadBase::getPowerManager_l() { Loading @@ -929,17 +950,8 @@ void AudioFlinger::ThreadBase::getPowerManager_l() { } } void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<uid_t> &uids) { void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<int> &uids) { getPowerManager_l(); #if !LOG_NDEBUG std::stringstream s; for (uid_t uid : uids) { s << uid << " "; } ALOGD("updateWakeLockUids_l %s uids:%s", mThreadName, s.str().c_str()); #endif if (mWakeLockToken == NULL) { // token may be NULL if AudioFlinger::systemReady() not called. if (mSystemReady) { ALOGE("no wake lock to update, but system ready!"); Loading Loading @@ -1501,41 +1513,6 @@ void AudioFlinger::ThreadBase::systemReady() mPendingConfigEvents.clear(); } template <typename T> ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) { ssize_t index = mActiveTracks.indexOf(track); if (index >= 0) { ALOGW("ActiveTracks<T>::add track %p already there", track.get()); return index; } mActiveTracksGeneration++; mLatestActiveTrack = track; BatteryNotifier::getInstance().noteStartAudio(track->uid()); return mActiveTracks.add(track); } template <typename T> ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) { ssize_t index = mActiveTracks.remove(track); if (index < 0) { ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get()); return index; } mActiveTracksGeneration++; BatteryNotifier::getInstance().noteStopAudio(track->uid()); // mLatestActiveTrack is not cleared even if is the same as track. return index; } template <typename T> void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() { for (const sp<T> &track : mActiveTracks) { BatteryNotifier::getInstance().noteStopAudio(track->uid()); } mLastActiveTracksGeneration = mActiveTracksGeneration; mActiveTracks.clear(); mLatestActiveTrack.clear(); } // ---------------------------------------------------------------------------- // Playback Loading @@ -1562,6 +1539,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mSuspended(0), mBytesWritten(0), mFramesWritten(0), mSuspendedFrames(0), mActiveTracksGeneration(0), // mStreamTypes[] initialized in constructor body mOutput(output), mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), Loading Loading @@ -1680,8 +1658,8 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar result.append(buffer); Track::appendDumpHeader(result); for (size_t i = 0; i < numactive; ++i) { sp<Track> track = mActiveTracks[i]; if (mTracks.indexOf(track) < 0) { sp<Track> track = mActiveTracks[i].promote(); if (track != 0 && mTracks.indexOf(track) < 0) { track->dump(buffer, SIZE, true); result.append(buffer); } Loading Loading @@ -2084,6 +2062,9 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) track->mResetDone = false; track->mPresentationCompleteFrames = 0; mActiveTracks.add(track); mWakeLockUids.add(track->uid()); mActiveTracksGeneration++; mLatestActiveTrack = track; sp<EffectChain> chain = getEffectChain_l(track->sessionId()); if (chain != 0) { ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), Loading Loading @@ -2718,7 +2699,11 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c } // indicate all active tracks in the chain for (const sp<Track> &track : mActiveTracks) { for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) { sp<Track> track = mActiveTracks[i].promote(); if (track == 0) { continue; } if (session == track->sessionId()) { ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session); chain->incActiveTrackCnt(); Loading Loading @@ -2765,7 +2750,11 @@ size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& if (chain == mEffectChains[i]) { mEffectChains.removeAt(i); // detach all active tracks from the chain for (const sp<Track> &track : mActiveTracks) { for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) { sp<Track> track = mActiveTracks[i].promote(); if (track == 0) { continue; } if (session == track->sessionId()) { ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d", chain.get(), session); Loading Loading @@ -2842,6 +2831,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() // FIXME could this be made local to while loop? writeFrames = 0; int lastGeneration = 0; cacheParameters_l(); mSleepTimeUs = mIdleSleepTimeUs; Loading Loading @@ -2939,9 +2930,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastWriteTime == -1 ? systemTime() : mLastWriteTime; } for (const sp<Track> &t : mActiveTracks) { if (!t->isFastTrack()) { const size_t size = mActiveTracks.size(); for (size_t i = 0; i < size; ++i) { sp<Track> t = mActiveTracks[i].promote(); if (t != 0 && !t->isFastTrack()) { t->updateTrackFrameInfo( t->mAudioTrackServerProxy->framesReleased(), mFramesWritten, Loading @@ -2962,6 +2954,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() if (!keepWakeLock()) { releaseWakeLock_l(); released = true; mWakeLockUids.clear(); mActiveTracksGeneration++; } ALOGV("wait async completion"); mWaitWorkCV.wait(mLock); Loading Loading @@ -2995,6 +2989,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() } releaseWakeLock_l(); mWakeLockUids.clear(); mActiveTracksGeneration++; // wait until we have something to do... ALOGV("%s going to sleep", myName.string()); mWaitWorkCV.wait(mLock); Loading @@ -3019,7 +3015,12 @@ bool AudioFlinger::PlaybackThread::threadLoop() // mMixerStatusIgnoringFastTracks is also updated internally mMixerStatus = prepareTracks_l(&tracksToRemove); mActiveTracks.updateWakeLockUids(this); // compare with previously applied list if (lastGeneration != mActiveTracksGeneration) { // update wakelock updateWakeLockUids_l(mWakeLockUids); lastGeneration = mActiveTracksGeneration; } // prevent any changes in effect chain list and in each effect chain // during mixing and effect process as the audio buffers could be deleted Loading Loading @@ -3237,6 +3238,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() } releaseWakeLock(); mWakeLockUids.clear(); mActiveTracksGeneration++; ALOGV("Thread %p type %d exiting", this, mType); return false; Loading @@ -3250,6 +3253,8 @@ void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tra for (size_t i=0 ; i<count ; i++) { const sp<Track>& track = tracksToRemove.itemAt(i); mActiveTracks.remove(track); mWakeLockUids.remove(track->uid()); mActiveTracksGeneration++; ALOGV("removeTracks_l removing track on session %d", track->sessionId()); sp<EffectChain> chain = getEffectChain_l(track->sessionId()); if (chain != 0) { Loading Loading @@ -3868,7 +3873,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found. for (size_t i=0 ; i<count ; i++) { const sp<Track> t = mActiveTracks[i]; const sp<Track> t = mActiveTracks[i].promote(); if (t == 0) { continue; } // this const just means the local variable doesn't change Track* const track = t.get(); Loading Loading @@ -4364,7 +4372,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac size_t i = __builtin_ctz(resetMask); ALOG_ASSERT(i < count); resetMask &= ~(1 << i); sp<Track> track = mActiveTracks[i]; sp<Track> t = mActiveTracks[i].promote(); if (t == 0) { continue; } Track* track = t.get(); ALOG_ASSERT(track->isFastTrack() && track->isStopped()); track->reset(); } Loading Loading @@ -4674,7 +4686,7 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr void AudioFlinger::DirectOutputThread::onAddNewTrack_l() { sp<Track> previousTrack = mPreviousTrack.promote(); sp<Track> latestTrack = mActiveTracks.getLatest(); sp<Track> latestTrack = mLatestActiveTrack.promote(); if (previousTrack != 0 && latestTrack != 0) { if (mType == DIRECT) { Loading @@ -4700,7 +4712,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep bool doHwResume = false; // find out which tracks need to be processed for (const sp<Track> &t : mActiveTracks) { for (size_t i = 0; i < count; i++) { sp<Track> t = mActiveTracks[i].promote(); // The track died recently if (t == 0) { continue; } if (t->isInvalid()) { ALOGW("An invalidated track shouldn't be in active list"); tracksToRemove->add(t); Loading @@ -4715,7 +4733,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // In theory an older track could underrun and restart after the new one starts // but as we only care about the transition phase between two tracks on a // direct output, it is not a problem to ignore the underrun case. sp<Track> l = mActiveTracks.getLatest(); sp<Track> l = mLatestActiveTrack.promote(); bool last = l.get() == track; if (track->isPausing()) { Loading Loading @@ -5249,7 +5267,12 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr ALOGV("OffloadThread::prepareTracks_l active tracks %zu", count); // find out which tracks need to be processed for (const sp<Track> &t : mActiveTracks) { for (size_t i = 0; i < count; i++) { sp<Track> t = mActiveTracks[i].promote(); // The track died recently if (t == 0) { continue; } Track* const track = t.get(); #ifdef VERY_VERY_VERBOSE_LOGGING audio_track_cblk_t* cblk = track->cblk(); Loading @@ -5258,7 +5281,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // In theory an older track could underrun and restart after the new one starts // but as we only care about the transition phase between two tracks on a // direct output, it is not a problem to ignore the underrun case. sp<Track> l = mActiveTracks.getLatest(); sp<Track> l = mLatestActiveTrack.promote(); bool last = l.get() == track; if (track->isInvalid()) { Loading Loading @@ -5717,7 +5740,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, #endif ) : ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady), mInput(input), mRsmpInBuffer(NULL), mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL), // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l() mRsmpInRear(0) #ifdef TEE_SINK Loading Loading @@ -5875,9 +5898,25 @@ bool AudioFlinger::RecordThread::threadLoop() reacquire_wakelock: sp<RecordTrack> activeTrack; int activeTracksGen; { Mutex::Autolock _l(mLock); acquireWakeLock_l(); size_t size = mActiveTracks.size(); activeTracksGen = mActiveTracksGen; if (size > 0) { // FIXME an arbitrary choice activeTrack = mActiveTracks[0]; acquireWakeLock_l(activeTrack->uid()); if (size > 1) { SortedVector<int> tmp; for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); } } else { acquireWakeLock_l(-1); } } // used to request a deferred sleep, to be executed later while mutex is unlocked Loading Loading @@ -5929,6 +5968,15 @@ reacquire_wakelock: goto reacquire_wakelock; } if (mActiveTracksGen != activeTracksGen) { activeTracksGen = mActiveTracksGen; SortedVector<int> tmp; for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); } bool doBroadcast = false; bool allStopped = true; for (size_t i = 0; i < size; ) { Loading @@ -5941,6 +5989,7 @@ reacquire_wakelock: } removeTrack_l(activeTrack); mActiveTracks.remove(activeTrack); mActiveTracksGen++; size--; continue; } Loading @@ -5950,6 +5999,7 @@ reacquire_wakelock: case TrackBase::PAUSING: mActiveTracks.remove(activeTrack); mActiveTracksGen++; doBroadcast = true; size--; continue; Loading Loading @@ -5989,8 +6039,6 @@ reacquire_wakelock: } } mActiveTracks.updateWakeLockUids(this); if (allStopped) { standbyIfNotAlreadyInStandby(); } Loading Loading @@ -6289,6 +6337,7 @@ unlock: track->invalidate(); } mActiveTracks.clear(); mActiveTracksGen++; mStartStopCond.broadcast(); } Loading Loading @@ -6542,6 +6591,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // or using a separate command thread recordTrack->mState = TrackBase::STARTING_1; mActiveTracks.add(recordTrack); mActiveTracksGen++; status_t status = NO_ERROR; if (recordTrack->isExternalTrack()) { mLock.unlock(); Loading @@ -6550,6 +6600,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // FIXME should verify that recordTrack is still in mActiveTracks if (status != NO_ERROR) { mActiveTracks.remove(recordTrack); mActiveTracksGen++; recordTrack->clearSyncStartEvent(); ALOGV("RecordThread::start error %d", status); return status; Loading services/audioflinger/Threads.h +13 −98 Original line number Diff line number Diff line Loading @@ -400,11 +400,11 @@ protected: effect_uuid_t mType; // effect type UUID }; void acquireWakeLock(); virtual void acquireWakeLock_l(); void acquireWakeLock(int uid = -1); virtual void acquireWakeLock_l(int uid = -1); void releaseWakeLock(); void releaseWakeLock_l(); void updateWakeLockUids_l(const SortedVector<uid_t> &uids); void updateWakeLockUids_l(const SortedVector<int> &uids); void getPowerManager_l(); void setEffectSuspended_l(const effect_uuid_t *type, bool suspend, Loading Loading @@ -478,88 +478,8 @@ protected: static const size_t kLogSize = 4 * 1024; sp<NBLog::Writer> mNBLogWriter; bool mSystemReady; bool mNotifiedBatteryStart; ExtendedTimestamp mTimestamp; // ActiveTracks is a sorted vector of track type T representing the // active tracks of threadLoop() to be considered by the locked prepare portion. // ActiveTracks should be accessed with the ThreadBase lock held. // // During processing and I/O, the threadLoop does not hold the lock; // hence it does not directly use ActiveTracks. Care should be taken // to hold local strong references or defer removal of tracks // if the threadLoop may still be accessing those tracks due to mix, etc. // // This class updates power information appropriately. // template <typename T> class ActiveTracks { public: ActiveTracks() : mActiveTracksGeneration(0) , mLastActiveTracksGeneration(0) { } ~ActiveTracks() { clear(); } // returns the last track added (even though it may have been // subsequently removed from ActiveTracks). // // Used for DirectOutputThread to ensure a flush is called when transitioning // to a new track (even though it may be on the same session). // Used for OffloadThread to ensure that volume and mixer state is // taken from the latest track added. // // The latest track is saved with a weak pointer to prevent keeping an // otherwise useless track alive. Thus the function will return nullptr // if the latest track has subsequently been removed and destroyed. sp<T> getLatest() { return mLatestActiveTrack.promote(); } // Updates ActiveTracks client uids to the thread wakelock. void updateWakeLockUids(sp<ThreadBase> thread, bool force = false) { if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) { thread->updateWakeLockUids_l(getWakeLockUids()); mLastActiveTracksGeneration = mActiveTracksGeneration; } } // SortedVector methods ssize_t add(const sp<T> &track); ssize_t remove(const sp<T> &track); size_t size() const { return mActiveTracks.size(); } ssize_t indexOf(const sp<T>& item) { return mActiveTracks.indexOf(item); } sp<T> operator[](size_t index) const { return mActiveTracks[index]; } typename SortedVector<sp<T>>::iterator begin() { return mActiveTracks.begin(); } typename SortedVector<sp<T>>::iterator end() { return mActiveTracks.end(); } void clear(); private: SortedVector<uid_t> getWakeLockUids() { SortedVector<uid_t> wakeLockUids; for (const sp<T> &track : mActiveTracks) { wakeLockUids.add(track->uid()); } return wakeLockUids; // moved by underlying SharedBuffer } SortedVector<sp<T>> mActiveTracks; int mActiveTracksGeneration; int mLastActiveTracksGeneration; wp<T> mLatestActiveTrack; // latest track added to ActiveTracks }; }; // --- PlaybackThread --- Loading Loading @@ -638,10 +558,6 @@ protected: virtual void preExit(); virtual bool keepWakeLock() const { return true; } virtual void acquireWakeLock_l() { ThreadBase::acquireWakeLock_l(); mActiveTracks.updateWakeLockUids(this, true /* force */); } public: Loading Loading @@ -814,7 +730,10 @@ private: bool mMasterMute; void setMasterMute_l(bool muted) { mMasterMute = muted; } protected: ActiveTracks<Track> mActiveTracks; SortedVector< wp<Track> > mActiveTracks; // FIXME check if this could be sp<> SortedVector<int> mWakeLockUids; int mActiveTracksGeneration; wp<Track> mLatestActiveTrack; // latest track added to mActiveTracks // Allocate a track name for a given channel mask. // Returns name >= 0 if successful, -1 on failure. Loading Loading @@ -980,8 +899,8 @@ protected: virtual uint32_t suspendSleepTimeUs() const; virtual void cacheParameters_l(); virtual void acquireWakeLock_l() { PlaybackThread::acquireWakeLock_l(); virtual void acquireWakeLock_l(int uid = -1) { PlaybackThread::acquireWakeLock_l(uid); if (hasFastMixer()) { mFastMixer->setBoottimeOffset( mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]); Loading Loading @@ -1420,11 +1339,6 @@ public: virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc, audio_session_t sessionId); virtual void acquireWakeLock_l() { ThreadBase::acquireWakeLock_l(); mActiveTracks.updateWakeLockUids(this, true /* force */); } private: // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); Loading @@ -1436,8 +1350,9 @@ private: SortedVector < sp<RecordTrack> > mTracks; // mActiveTracks has dual roles: it indicates the current active track(s), and // is used together with mStartStopCond to indicate start()/stop() progress ActiveTracks<RecordTrack> mActiveTracks; SortedVector< sp<RecordTrack> > mActiveTracks; // generation counter for mActiveTracks int mActiveTracksGen; Condition mStartStopCond; // resampler converts input at HAL Hz to output at AudioRecord client Hz Loading Loading
services/audioflinger/Threads.cpp +121 −70 Original line number Diff line number Diff line Loading @@ -508,7 +508,8 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio mAudioSource(AUDIO_SOURCE_DEFAULT), mId(id), // mName will be set by concrete (non-virtual) subclass mDeathRecipient(new PMDeathRecipient(this)), mSystemReady(systemReady) mSystemReady(systemReady), mNotifiedBatteryStart(false) { memset(&mPatch, 0, sizeof(struct audio_patch)); } Loading Loading @@ -849,10 +850,10 @@ void AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& } } void AudioFlinger::ThreadBase::acquireWakeLock() void AudioFlinger::ThreadBase::acquireWakeLock(int uid) { Mutex::Autolock _l(mLock); acquireWakeLock_l(); acquireWakeLock_l(uid); } String16 AudioFlinger::ThreadBase::getWakeLockTag() Loading @@ -874,23 +875,37 @@ String16 AudioFlinger::ThreadBase::getWakeLockTag() } } void AudioFlinger::ThreadBase::acquireWakeLock_l() void AudioFlinger::ThreadBase::acquireWakeLock_l(int uid) { getPowerManager_l(); if (mPowerManager != 0) { sp<IBinder> binder = new BBinder(); // Uses AID_AUDIOSERVER for wakelock. updateWakeLockUids_l() updates with client uids. status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, status_t status; if (uid >= 0) { status = mPowerManager->acquireWakeLockWithUid(POWERMANAGER_PARTIAL_WAKE_LOCK, binder, getWakeLockTag(), String16("audioserver"), uid, true /* FIXME force oneway contrary to .aidl */); } else { status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK, binder, getWakeLockTag(), String16("audioserver"), true /* FIXME force oneway contrary to .aidl */); } if (status == NO_ERROR) { mWakeLockToken = binder; } ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status); } if (!mNotifiedBatteryStart) { // TODO: call this function for each track when it becomes active. BatteryNotifier::getInstance().noteStartAudio(AID_AUDIOSERVER); mNotifiedBatteryStart = true; } gBoottime.acquire(mWakeLockToken); mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME] = gBoottime.getBoottimeOffset(); Loading @@ -913,6 +928,12 @@ void AudioFlinger::ThreadBase::releaseWakeLock_l() } mWakeLockToken.clear(); } if (mNotifiedBatteryStart) { // TODO: call this function for each track when it becomes inactive. BatteryNotifier::getInstance().noteStopAudio(AID_AUDIOSERVER); mNotifiedBatteryStart = false; } } void AudioFlinger::ThreadBase::getPowerManager_l() { Loading @@ -929,17 +950,8 @@ void AudioFlinger::ThreadBase::getPowerManager_l() { } } void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<uid_t> &uids) { void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<int> &uids) { getPowerManager_l(); #if !LOG_NDEBUG std::stringstream s; for (uid_t uid : uids) { s << uid << " "; } ALOGD("updateWakeLockUids_l %s uids:%s", mThreadName, s.str().c_str()); #endif if (mWakeLockToken == NULL) { // token may be NULL if AudioFlinger::systemReady() not called. if (mSystemReady) { ALOGE("no wake lock to update, but system ready!"); Loading Loading @@ -1501,41 +1513,6 @@ void AudioFlinger::ThreadBase::systemReady() mPendingConfigEvents.clear(); } template <typename T> ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) { ssize_t index = mActiveTracks.indexOf(track); if (index >= 0) { ALOGW("ActiveTracks<T>::add track %p already there", track.get()); return index; } mActiveTracksGeneration++; mLatestActiveTrack = track; BatteryNotifier::getInstance().noteStartAudio(track->uid()); return mActiveTracks.add(track); } template <typename T> ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) { ssize_t index = mActiveTracks.remove(track); if (index < 0) { ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get()); return index; } mActiveTracksGeneration++; BatteryNotifier::getInstance().noteStopAudio(track->uid()); // mLatestActiveTrack is not cleared even if is the same as track. return index; } template <typename T> void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() { for (const sp<T> &track : mActiveTracks) { BatteryNotifier::getInstance().noteStopAudio(track->uid()); } mLastActiveTracksGeneration = mActiveTracksGeneration; mActiveTracks.clear(); mLatestActiveTrack.clear(); } // ---------------------------------------------------------------------------- // Playback Loading @@ -1562,6 +1539,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mSuspended(0), mBytesWritten(0), mFramesWritten(0), mSuspendedFrames(0), mActiveTracksGeneration(0), // mStreamTypes[] initialized in constructor body mOutput(output), mLastWriteTime(-1), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false), Loading Loading @@ -1680,8 +1658,8 @@ void AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& ar result.append(buffer); Track::appendDumpHeader(result); for (size_t i = 0; i < numactive; ++i) { sp<Track> track = mActiveTracks[i]; if (mTracks.indexOf(track) < 0) { sp<Track> track = mActiveTracks[i].promote(); if (track != 0 && mTracks.indexOf(track) < 0) { track->dump(buffer, SIZE, true); result.append(buffer); } Loading Loading @@ -2084,6 +2062,9 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) track->mResetDone = false; track->mPresentationCompleteFrames = 0; mActiveTracks.add(track); mWakeLockUids.add(track->uid()); mActiveTracksGeneration++; mLatestActiveTrack = track; sp<EffectChain> chain = getEffectChain_l(track->sessionId()); if (chain != 0) { ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), Loading Loading @@ -2718,7 +2699,11 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c } // indicate all active tracks in the chain for (const sp<Track> &track : mActiveTracks) { for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) { sp<Track> track = mActiveTracks[i].promote(); if (track == 0) { continue; } if (session == track->sessionId()) { ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session); chain->incActiveTrackCnt(); Loading Loading @@ -2765,7 +2750,11 @@ size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& if (chain == mEffectChains[i]) { mEffectChains.removeAt(i); // detach all active tracks from the chain for (const sp<Track> &track : mActiveTracks) { for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) { sp<Track> track = mActiveTracks[i].promote(); if (track == 0) { continue; } if (session == track->sessionId()) { ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d", chain.get(), session); Loading Loading @@ -2842,6 +2831,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() // FIXME could this be made local to while loop? writeFrames = 0; int lastGeneration = 0; cacheParameters_l(); mSleepTimeUs = mIdleSleepTimeUs; Loading Loading @@ -2939,9 +2930,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = mLastWriteTime == -1 ? systemTime() : mLastWriteTime; } for (const sp<Track> &t : mActiveTracks) { if (!t->isFastTrack()) { const size_t size = mActiveTracks.size(); for (size_t i = 0; i < size; ++i) { sp<Track> t = mActiveTracks[i].promote(); if (t != 0 && !t->isFastTrack()) { t->updateTrackFrameInfo( t->mAudioTrackServerProxy->framesReleased(), mFramesWritten, Loading @@ -2962,6 +2954,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() if (!keepWakeLock()) { releaseWakeLock_l(); released = true; mWakeLockUids.clear(); mActiveTracksGeneration++; } ALOGV("wait async completion"); mWaitWorkCV.wait(mLock); Loading Loading @@ -2995,6 +2989,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() } releaseWakeLock_l(); mWakeLockUids.clear(); mActiveTracksGeneration++; // wait until we have something to do... ALOGV("%s going to sleep", myName.string()); mWaitWorkCV.wait(mLock); Loading @@ -3019,7 +3015,12 @@ bool AudioFlinger::PlaybackThread::threadLoop() // mMixerStatusIgnoringFastTracks is also updated internally mMixerStatus = prepareTracks_l(&tracksToRemove); mActiveTracks.updateWakeLockUids(this); // compare with previously applied list if (lastGeneration != mActiveTracksGeneration) { // update wakelock updateWakeLockUids_l(mWakeLockUids); lastGeneration = mActiveTracksGeneration; } // prevent any changes in effect chain list and in each effect chain // during mixing and effect process as the audio buffers could be deleted Loading Loading @@ -3237,6 +3238,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() } releaseWakeLock(); mWakeLockUids.clear(); mActiveTracksGeneration++; ALOGV("Thread %p type %d exiting", this, mType); return false; Loading @@ -3250,6 +3253,8 @@ void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tra for (size_t i=0 ; i<count ; i++) { const sp<Track>& track = tracksToRemove.itemAt(i); mActiveTracks.remove(track); mWakeLockUids.remove(track->uid()); mActiveTracksGeneration++; ALOGV("removeTracks_l removing track on session %d", track->sessionId()); sp<EffectChain> chain = getEffectChain_l(track->sessionId()); if (chain != 0) { Loading Loading @@ -3868,7 +3873,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac mEffectBufferValid = false; // mEffectBuffer has no valid data until tracks found. for (size_t i=0 ; i<count ; i++) { const sp<Track> t = mActiveTracks[i]; const sp<Track> t = mActiveTracks[i].promote(); if (t == 0) { continue; } // this const just means the local variable doesn't change Track* const track = t.get(); Loading Loading @@ -4364,7 +4372,11 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac size_t i = __builtin_ctz(resetMask); ALOG_ASSERT(i < count); resetMask &= ~(1 << i); sp<Track> track = mActiveTracks[i]; sp<Track> t = mActiveTracks[i].promote(); if (t == 0) { continue; } Track* track = t.get(); ALOG_ASSERT(track->isFastTrack() && track->isStopped()); track->reset(); } Loading Loading @@ -4674,7 +4686,7 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr void AudioFlinger::DirectOutputThread::onAddNewTrack_l() { sp<Track> previousTrack = mPreviousTrack.promote(); sp<Track> latestTrack = mActiveTracks.getLatest(); sp<Track> latestTrack = mLatestActiveTrack.promote(); if (previousTrack != 0 && latestTrack != 0) { if (mType == DIRECT) { Loading @@ -4700,7 +4712,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep bool doHwResume = false; // find out which tracks need to be processed for (const sp<Track> &t : mActiveTracks) { for (size_t i = 0; i < count; i++) { sp<Track> t = mActiveTracks[i].promote(); // The track died recently if (t == 0) { continue; } if (t->isInvalid()) { ALOGW("An invalidated track shouldn't be in active list"); tracksToRemove->add(t); Loading @@ -4715,7 +4733,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // In theory an older track could underrun and restart after the new one starts // but as we only care about the transition phase between two tracks on a // direct output, it is not a problem to ignore the underrun case. sp<Track> l = mActiveTracks.getLatest(); sp<Track> l = mLatestActiveTrack.promote(); bool last = l.get() == track; if (track->isPausing()) { Loading Loading @@ -5249,7 +5267,12 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr ALOGV("OffloadThread::prepareTracks_l active tracks %zu", count); // find out which tracks need to be processed for (const sp<Track> &t : mActiveTracks) { for (size_t i = 0; i < count; i++) { sp<Track> t = mActiveTracks[i].promote(); // The track died recently if (t == 0) { continue; } Track* const track = t.get(); #ifdef VERY_VERY_VERBOSE_LOGGING audio_track_cblk_t* cblk = track->cblk(); Loading @@ -5258,7 +5281,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // In theory an older track could underrun and restart after the new one starts // but as we only care about the transition phase between two tracks on a // direct output, it is not a problem to ignore the underrun case. sp<Track> l = mActiveTracks.getLatest(); sp<Track> l = mLatestActiveTrack.promote(); bool last = l.get() == track; if (track->isInvalid()) { Loading Loading @@ -5717,7 +5740,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, #endif ) : ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD, systemReady), mInput(input), mRsmpInBuffer(NULL), mInput(input), mActiveTracksGen(0), mRsmpInBuffer(NULL), // mRsmpInFrames, mRsmpInFramesP2, and mRsmpInFramesOA are set by readInputParameters_l() mRsmpInRear(0) #ifdef TEE_SINK Loading Loading @@ -5875,9 +5898,25 @@ bool AudioFlinger::RecordThread::threadLoop() reacquire_wakelock: sp<RecordTrack> activeTrack; int activeTracksGen; { Mutex::Autolock _l(mLock); acquireWakeLock_l(); size_t size = mActiveTracks.size(); activeTracksGen = mActiveTracksGen; if (size > 0) { // FIXME an arbitrary choice activeTrack = mActiveTracks[0]; acquireWakeLock_l(activeTrack->uid()); if (size > 1) { SortedVector<int> tmp; for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); } } else { acquireWakeLock_l(-1); } } // used to request a deferred sleep, to be executed later while mutex is unlocked Loading Loading @@ -5929,6 +5968,15 @@ reacquire_wakelock: goto reacquire_wakelock; } if (mActiveTracksGen != activeTracksGen) { activeTracksGen = mActiveTracksGen; SortedVector<int> tmp; for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); } bool doBroadcast = false; bool allStopped = true; for (size_t i = 0; i < size; ) { Loading @@ -5941,6 +5989,7 @@ reacquire_wakelock: } removeTrack_l(activeTrack); mActiveTracks.remove(activeTrack); mActiveTracksGen++; size--; continue; } Loading @@ -5950,6 +5999,7 @@ reacquire_wakelock: case TrackBase::PAUSING: mActiveTracks.remove(activeTrack); mActiveTracksGen++; doBroadcast = true; size--; continue; Loading Loading @@ -5989,8 +6039,6 @@ reacquire_wakelock: } } mActiveTracks.updateWakeLockUids(this); if (allStopped) { standbyIfNotAlreadyInStandby(); } Loading Loading @@ -6289,6 +6337,7 @@ unlock: track->invalidate(); } mActiveTracks.clear(); mActiveTracksGen++; mStartStopCond.broadcast(); } Loading Loading @@ -6542,6 +6591,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // or using a separate command thread recordTrack->mState = TrackBase::STARTING_1; mActiveTracks.add(recordTrack); mActiveTracksGen++; status_t status = NO_ERROR; if (recordTrack->isExternalTrack()) { mLock.unlock(); Loading @@ -6550,6 +6600,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // FIXME should verify that recordTrack is still in mActiveTracks if (status != NO_ERROR) { mActiveTracks.remove(recordTrack); mActiveTracksGen++; recordTrack->clearSyncStartEvent(); ALOGV("RecordThread::start error %d", status); return status; Loading
services/audioflinger/Threads.h +13 −98 Original line number Diff line number Diff line Loading @@ -400,11 +400,11 @@ protected: effect_uuid_t mType; // effect type UUID }; void acquireWakeLock(); virtual void acquireWakeLock_l(); void acquireWakeLock(int uid = -1); virtual void acquireWakeLock_l(int uid = -1); void releaseWakeLock(); void releaseWakeLock_l(); void updateWakeLockUids_l(const SortedVector<uid_t> &uids); void updateWakeLockUids_l(const SortedVector<int> &uids); void getPowerManager_l(); void setEffectSuspended_l(const effect_uuid_t *type, bool suspend, Loading Loading @@ -478,88 +478,8 @@ protected: static const size_t kLogSize = 4 * 1024; sp<NBLog::Writer> mNBLogWriter; bool mSystemReady; bool mNotifiedBatteryStart; ExtendedTimestamp mTimestamp; // ActiveTracks is a sorted vector of track type T representing the // active tracks of threadLoop() to be considered by the locked prepare portion. // ActiveTracks should be accessed with the ThreadBase lock held. // // During processing and I/O, the threadLoop does not hold the lock; // hence it does not directly use ActiveTracks. Care should be taken // to hold local strong references or defer removal of tracks // if the threadLoop may still be accessing those tracks due to mix, etc. // // This class updates power information appropriately. // template <typename T> class ActiveTracks { public: ActiveTracks() : mActiveTracksGeneration(0) , mLastActiveTracksGeneration(0) { } ~ActiveTracks() { clear(); } // returns the last track added (even though it may have been // subsequently removed from ActiveTracks). // // Used for DirectOutputThread to ensure a flush is called when transitioning // to a new track (even though it may be on the same session). // Used for OffloadThread to ensure that volume and mixer state is // taken from the latest track added. // // The latest track is saved with a weak pointer to prevent keeping an // otherwise useless track alive. Thus the function will return nullptr // if the latest track has subsequently been removed and destroyed. sp<T> getLatest() { return mLatestActiveTrack.promote(); } // Updates ActiveTracks client uids to the thread wakelock. void updateWakeLockUids(sp<ThreadBase> thread, bool force = false) { if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) { thread->updateWakeLockUids_l(getWakeLockUids()); mLastActiveTracksGeneration = mActiveTracksGeneration; } } // SortedVector methods ssize_t add(const sp<T> &track); ssize_t remove(const sp<T> &track); size_t size() const { return mActiveTracks.size(); } ssize_t indexOf(const sp<T>& item) { return mActiveTracks.indexOf(item); } sp<T> operator[](size_t index) const { return mActiveTracks[index]; } typename SortedVector<sp<T>>::iterator begin() { return mActiveTracks.begin(); } typename SortedVector<sp<T>>::iterator end() { return mActiveTracks.end(); } void clear(); private: SortedVector<uid_t> getWakeLockUids() { SortedVector<uid_t> wakeLockUids; for (const sp<T> &track : mActiveTracks) { wakeLockUids.add(track->uid()); } return wakeLockUids; // moved by underlying SharedBuffer } SortedVector<sp<T>> mActiveTracks; int mActiveTracksGeneration; int mLastActiveTracksGeneration; wp<T> mLatestActiveTrack; // latest track added to ActiveTracks }; }; // --- PlaybackThread --- Loading Loading @@ -638,10 +558,6 @@ protected: virtual void preExit(); virtual bool keepWakeLock() const { return true; } virtual void acquireWakeLock_l() { ThreadBase::acquireWakeLock_l(); mActiveTracks.updateWakeLockUids(this, true /* force */); } public: Loading Loading @@ -814,7 +730,10 @@ private: bool mMasterMute; void setMasterMute_l(bool muted) { mMasterMute = muted; } protected: ActiveTracks<Track> mActiveTracks; SortedVector< wp<Track> > mActiveTracks; // FIXME check if this could be sp<> SortedVector<int> mWakeLockUids; int mActiveTracksGeneration; wp<Track> mLatestActiveTrack; // latest track added to mActiveTracks // Allocate a track name for a given channel mask. // Returns name >= 0 if successful, -1 on failure. Loading Loading @@ -980,8 +899,8 @@ protected: virtual uint32_t suspendSleepTimeUs() const; virtual void cacheParameters_l(); virtual void acquireWakeLock_l() { PlaybackThread::acquireWakeLock_l(); virtual void acquireWakeLock_l(int uid = -1) { PlaybackThread::acquireWakeLock_l(uid); if (hasFastMixer()) { mFastMixer->setBoottimeOffset( mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]); Loading Loading @@ -1420,11 +1339,6 @@ public: virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc, audio_session_t sessionId); virtual void acquireWakeLock_l() { ThreadBase::acquireWakeLock_l(); mActiveTracks.updateWakeLockUids(this, true /* force */); } private: // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); Loading @@ -1436,8 +1350,9 @@ private: SortedVector < sp<RecordTrack> > mTracks; // mActiveTracks has dual roles: it indicates the current active track(s), and // is used together with mStartStopCond to indicate start()/stop() progress ActiveTracks<RecordTrack> mActiveTracks; SortedVector< sp<RecordTrack> > mActiveTracks; // generation counter for mActiveTracks int mActiveTracksGen; Condition mStartStopCond; // resampler converts input at HAL Hz to output at AudioRecord client Hz Loading