Wait for CaptureSessionState.disconnect when onSessionDisconnected
There are multiple paths that can lead to
CaptureSessionState.disconnect(), but notably when a prior capture
session is being disconnected to make way for a new capture session, it
is possible the prior CaptureSessionState is already being disconnected,
and we would hit an early return, with the prior capture session
possibly still being disconnected. Here we make sure we wait for the
CaptureSessionState to be disconnected before returning from
onSessionFinalized.
Bug: 383434693
Test: PreviewViewStreamStateTest
Change-Id: If8bf057fde74d1ecff01dd3d6673606954b2423d
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt
index e82afc7..c98a67a 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionState.kt
@@ -110,6 +110,8 @@
CLOSED
}
+ private val sessionDisconnected = CountDownLatch(1)
+
@GuardedBy("lock") private var hasAttemptedCaptureSession = false
private val captureSessionAttemptCompleted = CountDownLatch(1)
@@ -193,6 +195,13 @@
Log.debug { "$this session disconnecting" }
Debug.traceStart { "$this#onSessionDisconnected" }
disconnect()
+ // Important: CaptureSessionState can be disconnected on a separate path, and we may lose
+ // the race if another disconnect call was invoked in parallel. When that happens, we get
+ // an early return, but the winning disconnect call may still be in the process of
+ // disconnecting - notably doing stopRepeating() and abortCaptures(). We wait here such
+ // that we don't prematurely create a new capture session, which would close the capture
+ // session that is still being disconnected. See b/383434693 for details.
+ Debug.trace("$this#onSessionDisconnected Await") { sessionDisconnected.await() }
Debug.traceStop()
}
@@ -281,7 +290,7 @@
synchronized(lock) {
if (state == State.CLOSING || state == State.CLOSED) {
- return@synchronized
+ return
}
state = State.CLOSING
@@ -396,6 +405,9 @@
graphListener.onGraphStopped(null)
Debug.traceStop()
}
+
+ /** Do not remove - see [onSessionDisconnected] for details. */
+ sessionDisconnected.countDown()
}
/**