AudioFlinger: Associate audio time with client uid
Group active track operations for add and remove together.
PlaybackThread now uses strong pointer for active tracks.
Test: Play Music, Youtube, Batterystats, CTS AudioTrack
Bug: 32361950
Change-Id: I101df081dd8d090560a83c44c2fa9ffcbf39c84d
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index d261ea5..8607815 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -403,8 +403,8 @@
effect_uuid_t mType; // effect type UUID
};
- void acquireWakeLock(int uid = -1);
- virtual void acquireWakeLock_l(int uid = -1);
+ void acquireWakeLock();
+ virtual void acquireWakeLock_l();
void releaseWakeLock();
void releaseWakeLock_l();
void updateWakeLockUids_l(const SortedVector<int> &uids);
@@ -481,8 +481,92 @@
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() {
+ ALOGW_IF(!mActiveTracks.isEmpty(),
+ "ActiveTracks should be empty in destructor");
+ }
+ // 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();
+ }
+
+ // 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();
+ }
+
+ // Due to Binder recursion optimization, clear() and updatePowerState()
+ // cannot be called from a Binder thread because they may call back into
+ // the original calling process (system server) for BatteryNotifier
+ // (which requires a Java environment that may not be present).
+ // Hence, call clear() and updatePowerState() only from the
+ // ThreadBase thread.
+ void clear();
+ // periodically called in the threadLoop() to update power state uids.
+ void updatePowerState(sp<ThreadBase> thread, bool force = false);
+
+ private:
+ SortedVector<int> getWakeLockUids() {
+ SortedVector<int> wakeLockUids;
+ for (const sp<T> &track : mActiveTracks) {
+ wakeLockUids.add(track->uid());
+ }
+ return wakeLockUids; // moved by underlying SharedBuffer
+ }
+
+ std::map<uid_t, std::pair<ssize_t /* previous */, ssize_t /* current */>>
+ mBatteryCounter;
+ SortedVector<sp<T>> mActiveTracks;
+ int mActiveTracksGeneration;
+ int mLastActiveTracksGeneration;
+ wp<T> mLatestActiveTrack; // latest track added to ActiveTracks
+ };
};
// --- PlaybackThread ---
@@ -561,6 +645,10 @@
virtual void preExit();
virtual bool keepWakeLock() const { return true; }
+ virtual void acquireWakeLock_l() {
+ ThreadBase::acquireWakeLock_l();
+ mActiveTracks.updatePowerState(this, true /* force */);
+ }
public:
@@ -733,10 +821,7 @@
bool mMasterMute;
void setMasterMute_l(bool muted) { mMasterMute = muted; }
protected:
- SortedVector< wp<Track> > mActiveTracks; // FIXME check if this could be sp<>
- SortedVector<int> mWakeLockUids;
- int mActiveTracksGeneration;
- wp<Track> mLatestActiveTrack; // latest track added to mActiveTracks
+ ActiveTracks<Track> mActiveTracks;
// Allocate a track name for a given channel mask.
// Returns name >= 0 if successful, -1 on failure.
@@ -974,8 +1059,8 @@
virtual uint32_t suspendSleepTimeUs() const;
virtual void cacheParameters_l();
- virtual void acquireWakeLock_l(int uid = -1) {
- PlaybackThread::acquireWakeLock_l(uid);
+ virtual void acquireWakeLock_l() {
+ PlaybackThread::acquireWakeLock_l();
if (hasFastMixer()) {
mFastMixer->setBoottimeOffset(
mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]);
@@ -1414,6 +1499,11 @@
virtual status_t checkEffectCompatibility_l(const effect_descriptor_t *desc,
audio_session_t sessionId);
+ virtual void acquireWakeLock_l() {
+ ThreadBase::acquireWakeLock_l();
+ mActiveTracks.updatePowerState(this, true /* force */);
+ }
+
private:
// Enter standby if not already in standby, and set mStandby flag
void standbyIfNotAlreadyInStandby();
@@ -1425,9 +1515,8 @@
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
- SortedVector< sp<RecordTrack> > mActiveTracks;
- // generation counter for mActiveTracks
- int mActiveTracksGen;
+ ActiveTracks<RecordTrack> mActiveTracks;
+
Condition mStartStopCond;
// resampler converts input at HAL Hz to output at AudioRecord client Hz