AudioFlinger: fix capture stop sequence
Make sure that the HAL input stream is actually in standby when audio policy
is notified by stopInput().
There was a race condition where it was possible for a new capture stream to be started
in the interval between stopInput() notification and input stream going into
standby because of the state update and sleep sequence in the record thread loop.
Also make sure we interrupt the sleep period if a command is pending.
Bug: 29865791
Change-Id: Ife720fbd2e5d0df8792669dc724b1fd70f63ab8a
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6f827d9..0e564ea 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -5985,14 +5985,6 @@
for (;;) {
Vector< sp<EffectChain> > effectChains;
- // sleep with mutex unlocked
- if (sleepUs > 0) {
- ATRACE_BEGIN("sleep");
- usleep(sleepUs);
- ATRACE_END();
- sleepUs = 0;
- }
-
// activeTracks accumulates a copy of a subset of mActiveTracks
Vector< sp<RecordTrack> > activeTracks;
@@ -6013,6 +6005,15 @@
break;
}
+ // sleep with mutex unlocked
+ if (sleepUs > 0) {
+ ATRACE_BEGIN("sleep");
+ mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)sleepUs));
+ ATRACE_END();
+ sleepUs = 0;
+ continue;
+ }
+
// if no active track(s), then standby and release wakelock
size_t size = mActiveTracks.size();
if (size == 0) {
@@ -6036,6 +6037,7 @@
}
bool doBroadcast = false;
+ bool allStopped = true;
for (size_t i = 0; i < size; ) {
activeTrack = mActiveTracks[i];
@@ -6064,15 +6066,18 @@
case TrackBase::STARTING_1:
sleepUs = 10000;
i++;
+ allStopped = false;
continue;
case TrackBase::STARTING_2:
doBroadcast = true;
mStandby = false;
activeTrack->mState = TrackBase::ACTIVE;
+ allStopped = false;
break;
case TrackBase::ACTIVE:
+ allStopped = false;
break;
case TrackBase::IDLE:
@@ -6092,6 +6097,10 @@
fastTrack = activeTrack;
}
}
+
+ if (allStopped) {
+ standbyIfNotAlreadyInStandby();
+ }
if (doBroadcast) {
mStartStopCond.broadcast();
}
@@ -6674,6 +6683,8 @@
}
// note that threadLoop may still be processing the track at this point [without lock]
recordTrack->mState = TrackBase::PAUSING;
+ // signal thread to stop
+ mWaitWorkCV.broadcast();
// do not wait for mStartStopCond if exiting
if (exitPending()) {
return true;