1 /* <lambda>null2 * Copyright 2021 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 17 package androidx.camera.camera2.pipe.integration.testing 18 19 import android.hardware.camera2.CaptureRequest 20 import android.hardware.camera2.params.MeteringRectangle 21 import androidx.camera.camera2.pipe.AeMode 22 import androidx.camera.camera2.pipe.CameraGraph 23 import androidx.camera.camera2.pipe.CameraStream 24 import androidx.camera.camera2.pipe.Lock3ABehavior 25 import androidx.camera.camera2.pipe.Request 26 import androidx.camera.camera2.pipe.RequestTemplate 27 import androidx.camera.camera2.pipe.Result3A 28 import androidx.camera.camera2.pipe.StreamId 29 import androidx.camera.camera2.pipe.integration.adapter.CameraStateAdapter 30 import androidx.camera.camera2.pipe.integration.adapter.SessionConfigAdapter 31 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraComponent 32 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraConfig 33 import androidx.camera.camera2.pipe.integration.config.UseCaseGraphConfig 34 import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera 35 import androidx.camera.camera2.pipe.integration.impl.UseCaseCameraRequestControl 36 import androidx.camera.core.ImageCapture 37 import androidx.camera.core.imagecapture.CameraCapturePipeline 38 import androidx.camera.core.impl.CaptureConfig 39 import androidx.camera.core.impl.Config 40 import androidx.camera.core.impl.DeferrableSurface 41 import androidx.camera.core.impl.SessionConfig 42 import androidx.camera.testing.impl.FakeCameraCapturePipeline 43 import java.util.concurrent.TimeUnit.MILLISECONDS 44 import java.util.concurrent.TimeUnit.NANOSECONDS 45 import kotlinx.coroutines.CompletableDeferred 46 import kotlinx.coroutines.CoroutineScope 47 import kotlinx.coroutines.Deferred 48 import kotlinx.coroutines.Job 49 import kotlinx.coroutines.SupervisorJob 50 import kotlinx.coroutines.launch 51 import kotlinx.coroutines.withTimeoutOrNull 52 53 class FakeUseCaseCameraComponentBuilder : UseCaseCameraComponent.Builder { 54 var buildInvocationCount = 0 55 private var sessionConfigAdapter = SessionConfigAdapter(emptyList()) 56 private var cameraGraph = FakeCameraGraph() 57 private var streamConfigMap = mutableMapOf<CameraStream.Config, DeferrableSurface>() 58 59 private var config: UseCaseCameraConfig = 60 UseCaseCameraConfig( 61 emptyList(), 62 sessionConfigAdapter, 63 CameraStateAdapter(), 64 cameraGraph, 65 streamConfigMap, 66 sessionProcessorManager = null 67 ) 68 69 override fun config(config: UseCaseCameraConfig): UseCaseCameraComponent.Builder { 70 this.config = config 71 return this 72 } 73 74 override fun build(): UseCaseCameraComponent { 75 buildInvocationCount++ 76 return FakeUseCaseCameraComponent() 77 } 78 } 79 80 class FakeUseCaseCameraComponent() : UseCaseCameraComponent { 81 private val fakeUseCaseCamera = FakeUseCaseCamera() 82 private val cameraGraph = FakeCameraGraph() 83 private val cameraStateAdapter = CameraStateAdapter() 84 getUseCaseCameranull85 override fun getUseCaseCamera(): UseCaseCamera { 86 return fakeUseCaseCamera 87 } 88 getUseCaseGraphConfignull89 override fun getUseCaseGraphConfig(): UseCaseGraphConfig { 90 // TODO: Implement this properly once we need to use it with SessionProcessor enabled. 91 return UseCaseGraphConfig(cameraGraph, emptyMap(), cameraStateAdapter) 92 } 93 } 94 95 // TODO: Further implement the methods in this class as needed 96 open class FakeUseCaseCameraRequestControl( 97 private val scope: CoroutineScope = CoroutineScope(SupervisorJob()), 98 ) : UseCaseCameraRequestControl { 99 val addParameterCalls = mutableListOf<Map<CaptureRequest.Key<*>, Any>>() 100 var addParameterResult = CompletableDeferred(Unit) 101 var setConfigCalls = mutableListOf<RequestParameters>() 102 var setConfigResult = CompletableDeferred(Unit) 103 var setTorchResult = CompletableDeferred(Result3A(status = Result3A.Status.OK)) 104 105 // TODO - Implement thread-safety in the functions annotated with @AnyThread in 106 // UseCaseCameraRequestControl 107 setParametersAsyncnull108 override fun setParametersAsync( 109 type: UseCaseCameraRequestControl.Type, 110 values: Map<CaptureRequest.Key<*>, Any>, 111 optionPriority: Config.OptionPriority, 112 ): Deferred<Unit> { 113 addParameterCalls.add(values) 114 return addParameterResult 115 } 116 setConfigAsyncnull117 override fun setConfigAsync( 118 type: UseCaseCameraRequestControl.Type, 119 config: Config?, 120 tags: Map<String, Any>, 121 streams: Set<StreamId>?, 122 template: RequestTemplate?, 123 listeners: Set<Request.Listener>, 124 sessionConfig: SessionConfig?, 125 ): Deferred<Unit> { 126 setConfigCalls.add(RequestParameters(type, config, tags)) 127 return CompletableDeferred(Unit) 128 } 129 setTorchOnAsyncnull130 override fun setTorchOnAsync(): Deferred<Result3A> { 131 return setTorchResult 132 } 133 setTorchOffAsyncnull134 override fun setTorchOffAsync(aeMode: AeMode): Deferred<Result3A> { 135 return setTorchResult 136 } 137 138 var aeRegions: List<MeteringRectangle>? = null 139 var afRegions: List<MeteringRectangle>? = null 140 var awbRegions: List<MeteringRectangle>? = null 141 142 val focusMeteringCalls = mutableListOf<FocusMeteringParams>() 143 var focusMeteringResult = CompletableDeferred(Result3A(status = Result3A.Status.OK)) 144 var cancelFocusMeteringCallCount = 0 145 var cancelFocusMeteringResult = CompletableDeferred(Result3A(status = Result3A.Status.OK)) 146 147 var focusAutoCompletesAfterTimeout = true 148 startFocusAndMeteringAsyncnull149 override fun startFocusAndMeteringAsync( 150 aeRegions: List<MeteringRectangle>?, 151 afRegions: List<MeteringRectangle>?, 152 awbRegions: List<MeteringRectangle>?, 153 aeLockBehavior: Lock3ABehavior?, 154 afLockBehavior: Lock3ABehavior?, 155 awbLockBehavior: Lock3ABehavior?, 156 afTriggerStartAeMode: AeMode?, 157 timeLimitNs: Long, 158 ): Deferred<Result3A> { 159 this.aeRegions = aeRegions 160 this.afRegions = afRegions 161 this.awbRegions = awbRegions 162 163 focusMeteringCalls.add( 164 FocusMeteringParams( 165 aeRegions, 166 afRegions, 167 awbRegions, 168 aeLockBehavior, 169 afLockBehavior, 170 awbLockBehavior, 171 afTriggerStartAeMode, 172 timeLimitNs 173 ) 174 ) 175 176 if (focusAutoCompletesAfterTimeout) { 177 scope.launch { 178 withTimeoutOrNull(MILLISECONDS.convert(timeLimitNs, NANOSECONDS)) { 179 focusMeteringResult.await() 180 } 181 .let { result3A -> 182 if (result3A == null) { 183 focusMeteringResult.complete( 184 Result3A(status = Result3A.Status.TIME_LIMIT_REACHED) 185 ) 186 } 187 } 188 } 189 } 190 191 return focusMeteringResult 192 } 193 cancelFocusAndMeteringAsyncnull194 override fun cancelFocusAndMeteringAsync(): Deferred<Result3A> { 195 cancelFocusMeteringCallCount++ 196 return cancelFocusMeteringResult 197 } 198 issueSingleCaptureAsyncnull199 override fun issueSingleCaptureAsync( 200 captureSequence: List<CaptureConfig>, 201 @ImageCapture.CaptureMode captureMode: Int, 202 @ImageCapture.FlashType flashType: Int, 203 @ImageCapture.FlashMode flashMode: Int, 204 ): List<Deferred<Void?>> { 205 return captureSequence.map { CompletableDeferred<Void?>(null).apply { complete(null) } } 206 } 207 update3aRegionsnull208 override fun update3aRegions( 209 aeRegions: List<MeteringRectangle>?, 210 afRegions: List<MeteringRectangle>?, 211 awbRegions: List<MeteringRectangle>? 212 ): Deferred<Result3A> { 213 this.aeRegions = aeRegions 214 this.afRegions = afRegions 215 this.awbRegions = awbRegions 216 return CompletableDeferred(Result3A(status = Result3A.Status.OK)) 217 } 218 awaitSurfaceSetupnull219 override suspend fun awaitSurfaceSetup(): Boolean { 220 return true 221 } 222 closenull223 override fun close() {} 224 225 data class FocusMeteringParams( 226 val aeRegions: List<MeteringRectangle>? = null, 227 val afRegions: List<MeteringRectangle>? = null, 228 val awbRegions: List<MeteringRectangle>? = null, 229 val aeLockBehavior: Lock3ABehavior? = null, 230 val afLockBehavior: Lock3ABehavior? = null, 231 val awbLockBehavior: Lock3ABehavior? = null, 232 val afTriggerStartAeMode: AeMode? = null, 233 val timeLimitNs: Long = CameraGraph.Constants3A.DEFAULT_TIME_LIMIT_NS, 234 ) 235 236 data class RequestParameters( 237 val type: UseCaseCameraRequestControl.Type, 238 val config: Config?, 239 val tags: Map<String, Any> = emptyMap(), 240 ) 241 } 242 243 // TODO: Further implement the methods in this class as needed 244 class FakeUseCaseCamera( 245 override var requestControl: UseCaseCameraRequestControl = FakeUseCaseCameraRequestControl(), 246 ) : UseCaseCamera { getCameraCapturePipelinenull247 override suspend fun getCameraCapturePipeline( 248 captureMode: Int, 249 flashMode: Int, 250 flashType: Int 251 ): CameraCapturePipeline = FakeCameraCapturePipeline() 252 253 override fun close(): Job { 254 return CompletableDeferred(Unit) 255 } 256 } 257