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.compat 18 19 import androidx.annotation.GuardedBy 20 import androidx.camera.camera2.pipe.FrameInfo 21 import androidx.camera.camera2.pipe.FrameNumber 22 import androidx.camera.camera2.pipe.Request 23 import androidx.camera.camera2.pipe.RequestMetadata 24 import androidx.camera.camera2.pipe.integration.adapter.propagateTo 25 import androidx.camera.camera2.pipe.integration.config.CameraScope 26 import androidx.camera.camera2.pipe.integration.impl.Camera2ImplConfig 27 import androidx.camera.camera2.pipe.integration.impl.UseCaseCameraRequestControl 28 import androidx.camera.camera2.pipe.integration.impl.containsTag 29 import androidx.camera.camera2.pipe.integration.interop.CaptureRequestOptions 30 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop 31 import androidx.camera.core.CameraControl 32 import androidx.camera.core.impl.Config 33 import androidx.camera.core.impl.annotation.ExecutedBy 34 import dagger.Binds 35 import dagger.Module 36 import javax.inject.Inject 37 import kotlinx.coroutines.CompletableDeferred 38 import kotlinx.coroutines.Deferred 39 40 private const val TAG_KEY = "Camera2CameraControl.tag" 41 42 @JvmDefaultWithCompatibility 43 @ExperimentalCamera2Interop 44 public interface Camera2CameraControlCompat : Request.Listener { 45 public fun addRequestOption(bundle: CaptureRequestOptions) 46 47 public fun getRequestOption(): CaptureRequestOptions 48 49 public fun clearRequestOption() 50 51 public fun cancelCurrentTask() 52 53 public fun applyAsync( 54 requestControl: UseCaseCameraRequestControl?, 55 cancelPreviousTask: Boolean = true 56 ): Deferred<Void?> 57 58 @Module 59 public abstract class Bindings { 60 @Binds 61 public abstract fun bindCamera2CameraControlCompImpl( 62 impl: Camera2CameraControlCompatImpl 63 ): Camera2CameraControlCompat 64 } 65 } 66 67 @CameraScope 68 @ExperimentalCamera2Interop 69 public class Camera2CameraControlCompatImpl @Inject constructor() : Camera2CameraControlCompat { 70 71 private val lock = Any() 72 private val updateSignalLock = Any() 73 74 @GuardedBy("lock") private var configBuilder = Camera2ImplConfig.Builder() 75 @GuardedBy("updateSignalLock") private var updateSignal: CompletableDeferred<Void?>? = null 76 @GuardedBy("updateSignalLock") private var pendingSignal: CompletableDeferred<Void?>? = null 77 addRequestOptionnull78 override fun addRequestOption(bundle: CaptureRequestOptions) { 79 synchronized(lock) { 80 for (option in bundle.listOptions()) { 81 @Suppress("UNCHECKED_CAST") val objectOpt = option as Config.Option<Any> 82 configBuilder.mutableConfig.insertOption( 83 objectOpt, 84 Config.OptionPriority.ALWAYS_OVERRIDE, 85 bundle.retrieveOption(objectOpt) 86 ) 87 } 88 } 89 } 90 getRequestOptionnull91 override fun getRequestOption(): CaptureRequestOptions = 92 synchronized(lock) { CaptureRequestOptions.Builder.from(configBuilder.build()).build() } 93 clearRequestOptionnull94 override fun clearRequestOption() { 95 synchronized(lock) { configBuilder = Camera2ImplConfig.Builder() } 96 } 97 cancelCurrentTasknull98 override fun cancelCurrentTask(): Unit = 99 synchronized(updateSignalLock) { 100 updateSignal 101 ?.also { updateSignal = null } 102 ?.cancelSignal("The camera control has became inactive.") 103 pendingSignal 104 ?.also { pendingSignal = null } 105 ?.cancelSignal("The camera control has became inactive.") 106 } 107 applyAsyncnull108 override fun applyAsync( 109 requestControl: UseCaseCameraRequestControl?, 110 cancelPreviousTask: Boolean 111 ): Deferred<Void?> { 112 val signal: CompletableDeferred<Void?> = CompletableDeferred() 113 val config = synchronized(lock) { configBuilder.build() } 114 synchronized(updateSignalLock) { 115 if (requestControl != null) { 116 if (cancelPreviousTask) { 117 // Cancel the previous request signal if exist. 118 updateSignal?.cancelSignal() 119 } else { 120 // propagate the result to the previous updateSignal 121 updateSignal?.let { previousUpdateSignal -> 122 signal.propagateTo(previousUpdateSignal) 123 } 124 } 125 126 updateSignal = signal 127 requestControl.setConfigAsync( 128 type = UseCaseCameraRequestControl.Type.CAMERA2_CAMERA_CONTROL, 129 config = config, 130 tags = mapOf(TAG_KEY to signal.hashCode()) 131 ) 132 } else { 133 // If there is no camera for the parameter update, the signal would be treated as a 134 // pending signal, and the pending signal would be completed after the camera 135 // applied the parameter. 136 137 // Cancel the previous request signal if it exists. Only keep the latest signal. 138 pendingSignal?.cancelSignal() 139 pendingSignal = signal 140 } 141 } 142 143 return signal 144 } 145 cancelSignalnull146 private fun CompletableDeferred<Void?>.cancelSignal( 147 msg: String = "Camera2CameraControl was updated with new options." 148 ) = this.apply { completeExceptionally(CameraControl.OperationCanceledException(msg)) } 149 150 @ExecutedBy("UseCaseThreads") onCompletenull151 override fun onComplete( 152 requestMetadata: RequestMetadata, 153 frameNumber: FrameNumber, 154 result: FrameInfo 155 ): Unit = 156 synchronized(updateSignalLock) { 157 updateSignal?.apply { 158 if (requestMetadata.containsTag(TAG_KEY, hashCode())) { 159 // Going to complete the [updateSignal] if the result contains the [TAG_KEY] 160 complete(null) 161 updateSignal = null 162 163 // Also complete the [pendingSignal] if it exists. 164 pendingSignal?.also { 165 it.complete(null) 166 pendingSignal = null 167 } 168 } 169 } 170 } 171 } 172