Use a separate thread to disconnect registered streams.
When the stream is torn down due to request from AudioFlinger, the
streams in shared mode will try to disconnect all registered streams in
the data callback thread. This will trigger stop all streams. When the
last registered stream is stopped, data callback thread will be joined.
That will cause a dead lock since the join thread is called from the
command thread when calling stop, while the stream is stopped by the
data callback thread.
To fix that issue, a separated thread is spawned to disconnect
registered streams so that the data callback thread can be joined
correctly.
Bug: 207408882
Test: repo steps in the bug
Test: atest AAudioTests
Change-Id: I317101818a49aa6750da544e35321f82b384748f
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index bc769f0..95bd4bb 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -66,8 +66,7 @@
getFramesPerBurst(), timeoutNanos);
if (result == AAUDIO_ERROR_DISCONNECTED) {
ALOGD("%s() read() returned AAUDIO_ERROR_DISCONNECTED", __func__);
- // We do not need the returned vector.
- (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
+ AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync();
break;
} else if (result != getFramesPerBurst()) {
ALOGW("callbackLoop() read %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index f590fc8..2a5939f 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -147,8 +147,7 @@
getFramesPerBurst(), timeoutNanos);
if (result == AAUDIO_ERROR_DISCONNECTED) {
ALOGD("%s() write() returned AAUDIO_ERROR_DISCONNECTED", __func__);
- // We do not need the returned vector.
- (void) AAudioServiceEndpointShared::disconnectRegisteredStreams();
+ AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync();
break;
} else if (result != getFramesPerBurst()) {
ALOGW("callbackLoop() wrote %d / %d",
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 5af0a91..dd421fe 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -214,3 +214,12 @@
}
return result;
}
+
+void AAudioServiceEndpointShared::handleDisconnectRegisteredStreamsAsync() {
+ android::sp<AAudioServiceEndpointShared> holdEndpoint(this);
+ std::thread asyncTask([holdEndpoint]() {
+ // We do not need the returned vector.
+ holdEndpoint->disconnectRegisteredStreams();
+ });
+ asyncTask.detach();
+}
diff --git a/services/oboeservice/AAudioServiceEndpointShared.h b/services/oboeservice/AAudioServiceEndpointShared.h
index 8357567..3e760c4 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.h
+++ b/services/oboeservice/AAudioServiceEndpointShared.h
@@ -69,6 +69,8 @@
aaudio_result_t stopSharingThread();
+ void handleDisconnectRegisteredStreamsAsync();
+
// An MMAP stream that is shared by multiple clients.
android::sp<AudioStreamInternal> mStreamInternal;