audioflinger: fix track metadata updates to HAL
Fix two problems with track metadata updates:
1) send update to HAL before starting mmap streams
2) send update to HAL after changing the route
Bug: 235763725
Test: repro steps in bug
Change-Id: I2e67c75fde165f565368759913acdb207a693c75
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7ccf5a1..06e6a05 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4618,6 +4618,9 @@
if (configChanged) {
sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -4648,6 +4651,9 @@
} else {
status = mOutput->stream->legacyReleaseAudioPatch();
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9162,6 +9168,9 @@
track->logEndInterval();
track->logBeginInterval(pathSourcesAsString);
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9178,6 +9187,9 @@
} else {
status = mInput->stream->legacyReleaseAudioPatch();
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9474,8 +9486,10 @@
return mHalStream->getMmapPosition(position);
}
-status_t AudioFlinger::MmapThread::exitStandby()
+status_t AudioFlinger::MmapThread::exitStandby_l()
{
+ // The HAL must receive track metadata before starting the stream
+ updateMetadata_l();
status_t ret = mHalStream->start();
if (ret != NO_ERROR) {
ALOGE("%s: error mHalStream->start() = %d for first track", __FUNCTION__, ret);
@@ -9501,13 +9515,10 @@
status_t ret;
+ // For the first track, reuse portId and session allocated when the stream was opened.
if (*handle == mPortId) {
- // For the first track, reuse portId and session allocated when the stream was opened.
- ret = exitStandby();
- if (ret == NO_ERROR) {
- acquireWakeLock();
- }
- return ret;
+ acquireWakeLock();
+ return NO_ERROR;
}
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
@@ -9609,7 +9620,6 @@
}
}
-
mActiveTracks.add(track);
sp<EffectChain> chain = getEffectChain_l(mSessionId);
if (chain != 0) {
@@ -9620,11 +9630,16 @@
track->logBeginInterval(patchSinksToString(&mPatch)); // log to MediaMetrics
*handle = portId;
+
+ if (mActiveTracks.size() == 1) {
+ ret = exitStandby_l();
+ }
+
broadcast_l();
- ALOGV("%s DONE handle %d stream %p", __FUNCTION__, *handle, mHalStream.get());
+ ALOGV("%s DONE status %d handle %d stream %p", __FUNCTION__, ret, *handle, mHalStream.get());
- return NO_ERROR;
+ return ret;
}
status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
@@ -9636,7 +9651,6 @@
}
if (handle == mPortId) {
- mHalStream->stop();
releaseWakeLock();
return NO_ERROR;
}
@@ -9673,6 +9687,10 @@
chain->decTrackCnt();
}
+ if (mActiveTracks.isEmpty()) {
+ mHalStream->stop();
+ }
+
broadcast_l();
return NO_ERROR;
@@ -9943,6 +9961,9 @@
mPatch = *patch;
mDeviceId = deviceId;
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -9962,6 +9983,9 @@
} else {
status = mHalStream->legacyReleaseAudioPatch();
}
+ // Force meteadata update after a route change
+ mActiveTracks.setHasChanged();
+
return status;
}
@@ -10359,16 +10383,15 @@
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
}
-status_t AudioFlinger::MmapCaptureThread::exitStandby()
+status_t AudioFlinger::MmapCaptureThread::exitStandby_l()
{
{
// mInput might have been cleared by clearInput()
- Mutex::Autolock _l(mLock);
if (mInput != nullptr && mInput->stream != nullptr) {
mInput->stream->setGain(1.0f);
}
}
- return MmapThread::exitStandby();
+ return MmapThread::exitStandby_l();
}
AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 074ae8f..c7ba5c4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -786,6 +786,11 @@
*/
bool readAndClearHasChanged();
+ /** Force updating track metadata to audio HAL stream next time
+ * readAndClearHasChanged() is called.
+ */
+ void setHasChanged() { mHasChanged = true; }
+
private:
void logTrack(const char *funcName, const sp<T> &track) const;
@@ -2014,7 +2019,7 @@
virtual void threadLoop_exit();
virtual void threadLoop_standby();
virtual bool shouldStandby_l() { return false; }
- virtual status_t exitStandby();
+ virtual status_t exitStandby_l() REQUIRES(mLock);
virtual status_t initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
virtual size_t frameCount() const { return mFrameCount; }
@@ -2165,7 +2170,7 @@
AudioStreamIn* clearInput();
- status_t exitStandby() override;
+ status_t exitStandby_l() REQUIRES(mLock) override;
void updateMetadata_l() override;
void processVolume_l() override;