1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package androidx.camera.camera2.pipe 17 18 import androidx.annotation.RestrictTo 19 import androidx.camera.camera2.pipe.graph.GraphListener 20 import kotlinx.coroutines.Deferred 21 import kotlinx.coroutines.flow.Flow 22 import kotlinx.coroutines.flow.flowOf 23 24 /** This is used to uniquely identify a specific backend implementation. */ 25 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 26 @JvmInline 27 public value class CameraBackendId(public val value: String) 28 29 /** 30 * A CameraBackend is used by [CameraPipe] to abstract out the lifecycle, state, and interactions 31 * with a set of camera devices in a standard way. 32 * 33 * Each [CameraBackend] is responsible for interacting with all of the individual cameras that are 34 * available through this backend. Since cameras often have complicated lifecycles and expensive 35 * interactions, this object serves as a low level facade that is used to manage access _across_ all 36 * cameras exposed by this backend. 37 * 38 * The lifecycle of an individual camera is managed by [CameraController]s, which may be created via 39 * [CameraBackend.createCameraController]. 40 */ 41 @JvmDefaultWithCompatibility 42 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 43 public interface CameraBackend { 44 public val id: CameraBackendId 45 46 /** 47 * A flow of the list of currently openable [CameraId]s from this CameraBackend. It should 48 * continuously return a list of current cameras, and the list should be updated as camera 49 * availability changes, e.g., an external camera is plugged or unplugged. The flow should also 50 * replay the most recent value for each new subscriber. 51 */ 52 public val cameraIds: Flow<List<CameraId>> 53 get() = flowOf(awaitCameraIds() ?: emptyList()) 54 55 /** 56 * Read out a list of _openable_ [CameraId]s for this backend. The backend may be able to report 57 * Metadata for non-openable cameras. However, these cameras should not appear the list of 58 * cameras returned by [getCameraIds]. 59 */ getCameraIdsnull60 public suspend fun getCameraIds(): List<CameraId>? = awaitCameraIds() 61 62 /** Thread-blocking version of [getCameraIds] for compatibility. */ 63 public fun awaitCameraIds(): List<CameraId>? 64 65 /** 66 * Read out a set of [CameraId] sets that can be operated concurrently. When multiple cameras 67 * are open, the number of configurable streams, as well as their sizes, might be considerably 68 * limited. 69 */ 70 public suspend fun getConcurrentCameraIds(): Set<Set<CameraId>>? = awaitConcurrentCameraIds() 71 72 /** Thread-blocking version of [getConcurrentCameraIds] for compatibility. */ 73 public fun awaitConcurrentCameraIds(): Set<Set<CameraId>>? 74 75 /** 76 * Retrieve [CameraMetadata] for this backend. Backends may cache the results of these calls. 77 * 78 * This call should should always succeed if the [CameraId] is in the list of ids returned by 79 * [getCameraIds]. For some backends, it may be possible to retrieve metadata for cameras that 80 * cannot be opened directly. 81 */ 82 public suspend fun getCameraMetadata(cameraId: CameraId): CameraMetadata? = 83 awaitCameraMetadata(cameraId) 84 85 /** Thread-blocking version of [getCameraMetadata] for compatibility. */ 86 public fun awaitCameraMetadata(cameraId: CameraId): CameraMetadata? 87 88 /** 89 * Stops all active [CameraController]s, which may disconnect any cached camera connection(s). 90 * This may be called on the main thread, and any long running background operations should be 91 * executed in the background. Once all connections are fully closed, the returned [Deferred] 92 * should be completed. 93 * 94 * Subsequent [CameraController]s may still be created after invoking [disconnectAllAsync], and 95 * existing [CameraController]s may attempt to restart. 96 */ 97 public fun disconnectAllAsync(): Deferred<Unit> 98 99 /** 100 * Shutdown this backend, closing active [CameraController]s, and clearing any cached resources. 101 * 102 * This method should be used carefully, as it can cause expensive reloading and re-querying of 103 * camera lists, metadata, and state. Once a backend instance has been shut down it should not 104 * be reused, and a new instance must be recreated. 105 */ 106 public fun shutdownAsync(): Deferred<Unit> 107 108 /** 109 * Creates a new [CameraController] instance that can be used to initialize and interact with a 110 * specific Camera that is available from this CameraBackend. Creating a [CameraController] 111 * should _not_ begin opening or interacting with the Camera until [CameraController.start] is 112 * called. 113 */ 114 public fun createCameraController( 115 cameraContext: CameraContext, 116 graphId: CameraGraphId, 117 graphConfig: CameraGraph.Config, 118 graphListener: GraphListener, 119 streamGraph: StreamGraph, 120 surfaceTracker: SurfaceTracker, 121 ): CameraController 122 123 /** Connects and starts the underlying camera */ 124 public fun prewarm(cameraId: CameraId) 125 126 /** Disconnects the underlying camera. */ 127 public fun disconnect(cameraId: CameraId) 128 129 /** 130 * Disconnects the underlying camera. Once the connection is closed, the returned [Deferred] 131 * should be completed. 132 */ 133 public fun disconnectAsync(cameraId: CameraId): Deferred<Unit> 134 135 /** Disconnects all active Cameras. */ 136 public fun disconnectAll() 137 } 138 139 /** 140 * Factory for creating a new [CameraBackend]. 141 * 142 * [CameraBackend] instances should not be cached by the factory instance, as the lifecycle of 143 * returned instances is managed by [CameraPipe] unless the application asks [CameraPipe] to close 144 * and release previously created [CameraBackend]s. 145 */ 146 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 147 public fun interface CameraBackendFactory { 148 /** Create a new [CameraBackend] instance based on the provided [CameraContext]. */ 149 public fun create(cameraContext: CameraContext): CameraBackend 150 } 151 152 /** 153 * Api for requesting and interacting with [CameraBackend] that are available in the current 154 * [CameraPipe] instance. 155 */ 156 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 157 public interface CameraBackends { 158 /** 159 * This provides access to the default [CameraBackend]. Accessing this property will create the 160 * backend if it is not already created. 161 */ 162 public val default: CameraBackend 163 164 /** 165 * This provides a list of all available [CameraBackend] instances, including the default one. 166 * Accessing this set will not create or initialize [CameraBackend] instances. 167 */ 168 public val allIds: Set<CameraBackendId> 169 170 /** 171 * This provides a list of [CameraBackend] instances that have been loaded, including the 172 * default camera backend. Accessing this set will not create or initialize [CameraBackend] 173 * instances. 174 */ 175 public val activeIds: Set<CameraBackendId> 176 177 /** This instructs all backends to each shutdown their respective cameras. */ shutdownnull178 public suspend fun shutdown() 179 180 /** 181 * Get a previously created [CameraBackend] instance, or create a new one. If the backend fails 182 * to load or is not available, this method will return null. 183 */ 184 public operator fun get(backendId: CameraBackendId): CameraBackend? 185 } 186