1 /* 2 * Copyright 2024 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.internal 18 19 import android.hardware.camera2.CaptureRequest 20 import androidx.annotation.GuardedBy 21 import androidx.camera.camera2.pipe.CameraGraph 22 import androidx.camera.camera2.pipe.Metadata 23 import androidx.camera.camera2.pipe.config.CameraGraphScope 24 import androidx.camera.camera2.pipe.config.ForCameraGraph 25 import androidx.camera.camera2.pipe.core.Log.warn 26 import androidx.camera.camera2.pipe.graph.GraphProcessor 27 import androidx.camera.camera2.pipe.graph.SessionLock 28 import javax.inject.Inject 29 import kotlinx.coroutines.CoroutineScope 30 31 @CameraGraphScope 32 public class CameraGraphParametersImpl 33 @Inject 34 internal constructor( 35 private val sessionLock: SessionLock, 36 private val graphProcessor: GraphProcessor, 37 @ForCameraGraph private val graphScope: CoroutineScope 38 ) : CameraGraph.Parameters { 39 private val lock = Any() 40 41 @GuardedBy("lock") private val parameters = mutableMapOf<Any, Any?>() 42 43 /** 44 * Set to true when [parameters] is modified. Set to false when the modified [parameters] is 45 * fetched. 46 */ 47 @GuardedBy("lock") private var dirty = false 48 49 @Suppress("UNCHECKED_CAST") getnull50 public override operator fun <T> get(key: CaptureRequest.Key<T>): T? = 51 synchronized(lock) { parameters[key] as T } 52 53 @Suppress("UNCHECKED_CAST") getnull54 public override operator fun <T> get(key: Metadata.Key<T>): T? = 55 synchronized(lock) { parameters[key] as T } 56 setnull57 public override operator fun <T : Any> set(key: CaptureRequest.Key<T>, value: T?) { 58 59 setAll(mapOf(key to value)) 60 } 61 setnull62 public override operator fun <T : Any> set(key: Metadata.Key<T>, value: T?) { 63 setAll(mapOf(key to value)) 64 } 65 setAllnull66 public override fun setAll(newParameters: Map<Any, Any?>) { 67 var invokeUpdate = false 68 synchronized(lock) { 69 var modified = false 70 for ((key, value) in newParameters.entries) { 71 modified = modify(parameters, key, value) || modified 72 } 73 if (modified && !dirty) { 74 dirty = true 75 invokeUpdate = true 76 } 77 } 78 applyUpdate(invokeUpdate) 79 } 80 modifynull81 private fun modify(map: MutableMap<Any, Any?>, key: Any, value: Any?): Boolean { 82 if (key !is CaptureRequest.Key<*> && key !is Metadata.Key<*>) { 83 warn { 84 "Skipping set parameter (key=$key, value=$value). $key is not a valid parameter type." 85 } 86 return false 87 } 88 var modified = false 89 if (!map.containsKey(key)) { 90 modified = true 91 } 92 if (map[key] != value) { 93 modified = true 94 } 95 map[key] = value 96 return modified 97 } 98 clearnull99 public override fun clear() { 100 var invokeUpdate = false 101 synchronized(lock) { 102 var modified = false 103 if (parameters.isNotEmpty()) { 104 parameters.clear() 105 modified = true 106 } 107 if (modified && !dirty) { 108 dirty = true 109 invokeUpdate = true 110 } 111 } 112 applyUpdate(invokeUpdate) 113 } 114 removenull115 public override fun <T> remove(key: CaptureRequest.Key<T>): Boolean { 116 return removeAll(setOf(key)) 117 } 118 removenull119 public override fun <T> remove(key: Metadata.Key<T>): Boolean { 120 return removeAll(setOf(key)) 121 } 122 removeAllnull123 public override fun removeAll(keys: Set<*>): Boolean { 124 var invokeUpdate = false 125 var modified = false 126 synchronized(lock) { 127 for (key in keys) { 128 if (parameters.containsKey(key)) { 129 parameters.remove(key) 130 modified = true 131 } 132 if (key !is CaptureRequest.Key<*> && key !is Metadata.Key<*>) { 133 warn { 134 "Skipping removing parameter with key $key. $key is not a valid parameter type." 135 } 136 } 137 } 138 if (modified && !dirty) { 139 dirty = true 140 invokeUpdate = true 141 } 142 } 143 applyUpdate(invokeUpdate) 144 return modified 145 } 146 147 /** 148 * Return the latest parameters if the class stored parameters has changed since the last time 149 * this method is called. If there is no parameter changes, return null. 150 */ fetchUpdatedParametersnull151 public fun fetchUpdatedParameters(): Map<Any, Any?>? { 152 synchronized(lock) { 153 if (!dirty) return null 154 155 dirty = false 156 return parameters 157 } 158 } 159 applyUpdatenull160 private fun applyUpdate(update: Boolean) { 161 val unappliedParameters = fetchUpdatedParameters() ?: return 162 if (update) { 163 sessionLock.withTokenIn(graphScope) { 164 graphProcessor.updateGraphParameters(unappliedParameters) 165 } 166 } 167 } 168 } 169