Merge "Add test-only API to shutdown all cameras" into androidx-main
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index aa924ea..3ac0b9a 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -28,6 +28,7 @@
import android.os.Build
import androidx.annotation.GuardedBy
import androidx.annotation.VisibleForTesting
+import androidx.camera.camera2.pipe.CameraDevices
import androidx.camera.camera2.pipe.CameraGraph
import androidx.camera.camera2.pipe.CameraGraph.OperatingMode
import androidx.camera.camera2.pipe.CameraGraph.RepeatingRequestRequirementsBeforeCapture.CompletionBehavior.AT_LEAST
@@ -124,6 +125,7 @@
@Inject
constructor(
private val cameraPipe: CameraPipe,
+ private val cameraDevices: CameraDevices,
@GuardedBy("lock") private val cameraCoordinator: CameraCoordinator,
private val callbackMap: CameraCallbackMap,
private val requestListener: ComboRequestListener,
@@ -352,6 +354,7 @@
closingCameraJobs.toList()
}
closingJobs.joinAll()
+ cameraDevices.disconnectAll()
}
override fun toString(): String = "UseCaseManager<${cameraConfig.cameraId}>"
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
index cfc6583..6ef0d69 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
@@ -56,6 +56,8 @@
import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
import androidx.camera.camera2.pipe.integration.testing.FakeSessionProcessor
import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraComponentBuilder
+import androidx.camera.camera2.pipe.testing.FakeCameraBackend
+import androidx.camera.camera2.pipe.testing.FakeCameraDevices
import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageCapture
@@ -677,8 +679,15 @@
FakeCameraMetadata(cameraId = cameraId, characteristics = characteristicsMap)
val fakeCamera = FakeCamera()
val cameraPipe = CameraPipe(CameraPipe.Config(ApplicationProvider.getApplicationContext()))
+ val fakeCameraBackend = FakeCameraBackend(mapOf(cameraId to fakeCameraMetadata))
return UseCaseManager(
cameraPipe = cameraPipe,
+ cameraDevices =
+ FakeCameraDevices(
+ fakeCameraBackend.id,
+ emptySet(),
+ mapOf(fakeCameraBackend.id to listOf(fakeCameraMetadata))
+ ),
cameraCoordinator = CameraCoordinatorAdapter(cameraPipe, cameraPipe.cameras()),
callbackMap = CameraCallbackMap(),
requestListener = ComboRequestListener(),
@@ -731,7 +740,7 @@
private fun createFakePreview(customDeferrableSurface: DeferrableSurface? = null) =
createFakeTestUseCase(
"Preview",
- CameraDevice.TEMPLATE_PREVIEW,
+ TEMPLATE_PREVIEW,
Preview::class.java,
customDeferrableSurface,
)
@@ -747,7 +756,7 @@
private fun createFakeImageAnalysis(customDeferrableSurface: DeferrableSurface? = null) =
createFakeTestUseCase(
"ImageAnalysis",
- CameraDevice.TEMPLATE_PREVIEW,
+ TEMPLATE_PREVIEW,
ImageAnalysis::class.java,
customDeferrableSurface,
)
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
index 5d5ee33..7b30d01 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
@@ -189,6 +189,9 @@
*/
public val activeIds: Set<CameraBackendId>
+ /** This instructs all backends to each shutdown their respective cameras. */
+ public suspend fun shutdown()
+
/**
* Get a previously created [CameraBackend] instance, or create a new one. If the backend fails
* to load or is not available, this method will return null.
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
index 6c16c76..e337f8e 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/CameraPipeComponent.kt
@@ -70,6 +70,8 @@
fun cameras(): CameraDevices
+ fun cameraBackends(): CameraBackends
+
fun cameraSurfaceManager(): CameraSurfaceManager
fun cameraAudioRestrictionController(): AudioRestrictionController
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt
index c0ddb86..4ac087e 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraBackendsImpl.kt
@@ -25,6 +25,7 @@
import androidx.camera.camera2.pipe.CameraContext
import androidx.camera.camera2.pipe.config.CameraPipeContext
import androidx.camera.camera2.pipe.core.Threads
+import kotlinx.coroutines.joinAll
/** Provides an implementation for interacting with CameraBackends. */
internal class CameraBackendsImpl(
@@ -50,6 +51,11 @@
override val activeIds: Set<CameraBackendId>
get() = synchronized(lock) { activeCameraBackends.keys }
+ override suspend fun shutdown() {
+ val shutdownJobs = activeCameraBackends.map { it.value.shutdownAsync() }
+ shutdownJobs.joinAll()
+ }
+
override fun get(backendId: CameraBackendId): CameraBackend? {
synchronized(lock) {
val existing = activeCameraBackends[backendId]