aaudio: pass smart pointer to mixer thread
Before this, the mixer thread could close the stream using a stale pointer.
This could cause timeouts when plugging headphones in or out.
Bug: 76092458
Test: write_sine_callback -m3 -pl -s1000
Test: unplug and replug headphones many times on Marlin
Change-Id: I437eb756686446a75fc5d04bc09d9408816585de
diff --git a/services/oboeservice/AAudioServiceEndpointShared.cpp b/services/oboeservice/AAudioServiceEndpointShared.cpp
index 584efe5..f08a52f 100644
--- a/services/oboeservice/AAudioServiceEndpointShared.cpp
+++ b/services/oboeservice/AAudioServiceEndpointShared.cpp
@@ -89,18 +89,22 @@
}
// Glue between C and C++ callbacks.
-static void *aaudio_endpoint_thread_proc(void *context) {
- AAudioServiceEndpointShared *endpoint = (AAudioServiceEndpointShared *) context;
- if (endpoint != NULL) {
- void *result = endpoint->callbackLoop();
- // Close now so that the HW resource is freed and we can open a new device.
- if (!endpoint->isConnected()) {
- endpoint->close();
- }
- return result;
- } else {
- return NULL;
+static void *aaudio_endpoint_thread_proc(void *arg) {
+ assert(arg != nullptr);
+
+ // The caller passed in a smart pointer to prevent the endpoint from getting deleted
+ // while the thread was launching.
+ sp<AAudioServiceEndpointShared> *endpointForThread =
+ static_cast<sp<AAudioServiceEndpointShared> *>(arg);
+ sp<AAudioServiceEndpointShared> endpoint = *endpointForThread;
+ delete endpointForThread; // Just use scoped smart pointer. Don't need this anymore.
+ void *result = endpoint->callbackLoop();
+ // Close now so that the HW resource is freed and we can open a new device.
+ if (!endpoint->isConnected()) {
+ endpoint->close();
}
+
+ return result;
}
aaudio_result_t aaudio::AAudioServiceEndpointShared::startSharingThread_l() {
@@ -109,7 +113,16 @@
* AAUDIO_NANOS_PER_SECOND
/ getSampleRate();
mCallbackEnabled.store(true);
- return getStreamInternal()->createThread(periodNanos, aaudio_endpoint_thread_proc, this);
+ // Pass a smart pointer so the thread can hold a reference.
+ sp<AAudioServiceEndpointShared> *endpointForThread = new sp<AAudioServiceEndpointShared>(this);
+ aaudio_result_t result = getStreamInternal()->createThread(periodNanos,
+ aaudio_endpoint_thread_proc,
+ endpointForThread);
+ if (result != AAUDIO_OK) {
+ // The thread can't delete it so we have to do it here.
+ delete endpointForThread;
+ }
+ return result;
}
aaudio_result_t aaudio::AAudioServiceEndpointShared::stopSharingThread() {