1 /*
2  * 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.graph
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.AfMode
23 import androidx.camera.camera2.pipe.AwbMode
24 import androidx.camera.camera2.pipe.FlashMode
25 import androidx.camera.camera2.pipe.config.CameraGraphScope
26 import javax.inject.Inject
27 
28 /**
29  * Holds the most recent 3A state for a single CameraGraph.
30  *
31  * This object is used to maintain the key-value pairs for the most recent 3A state that is used
32  * when building the requests that are sent to a CameraCaptureSession.
33  *
34  * The state is comprised of the modes, metering regions for ae, af and awb, and locks for ae and
35  * awb. We don't track the lock for af since af lock is achieved by setting 'af trigger = start' in
36  * in a request and then omitting the af trigger field in the subsequent requests doesn't disturb
37  * the af state. However for ae and awb, the lock type is boolean and should be explicitly set to
38  * 'true' in the subsequent requests once we have locked ae/awb and want them to stay locked.
39  */
40 @CameraGraphScope
41 internal class GraphState3A @Inject constructor() {
42     var aeMode: AeMode? = null
<lambda>null43         get() = synchronized(this) { field }
44         private set
45 
46     var afMode: AfMode? = null
<lambda>null47         get() = synchronized(this) { field }
48         private set
49 
50     var awbMode: AwbMode? = null
<lambda>null51         get() = synchronized(this) { field }
52         private set
53 
54     var flashMode: FlashMode? = null
<lambda>null55         get() = synchronized(this) { field }
56         private set
57 
58     var aeRegions: List<MeteringRectangle>? = null
<lambda>null59         get() = synchronized(this) { field }
60         private set
61 
62     var afRegions: List<MeteringRectangle>? = null
<lambda>null63         get() = synchronized(this) { field }
64         private set
65 
66     var awbRegions: List<MeteringRectangle>? = null
<lambda>null67         get() = synchronized(this) { field }
68         private set
69 
70     var aeLock: Boolean? = null
<lambda>null71         get() = synchronized(this) { field }
72         private set
73 
74     var awbLock: Boolean? = null
<lambda>null75         get() = synchronized(this) { field }
76         private set
77 
updatenull78     fun update(
79         aeMode: AeMode? = null,
80         afMode: AfMode? = null,
81         awbMode: AwbMode? = null,
82         flashMode: FlashMode? = null,
83         aeRegions: List<MeteringRectangle>? = null,
84         afRegions: List<MeteringRectangle>? = null,
85         awbRegions: List<MeteringRectangle>? = null,
86         aeLock: Boolean? = null,
87         awbLock: Boolean? = null
88     ) {
89         synchronized(this) {
90             aeMode?.let { this.aeMode = it }
91             afMode?.let { this.afMode = it }
92             awbMode?.let { this.awbMode = it }
93             flashMode?.let { this.flashMode = it }
94             aeRegions?.let { this.aeRegions = it.ifEmpty { null } }
95             afRegions?.let { this.afRegions = it.ifEmpty { null } }
96             awbRegions?.let { this.awbRegions = it.ifEmpty { null } }
97             aeLock?.let { this.aeLock = it }
98             awbLock?.let { this.awbLock = it }
99         }
100     }
101 
readStatenull102     fun readState(): Map<CaptureRequest.Key<*>, Any> {
103         synchronized(this) {
104             val map = mutableMapOf<CaptureRequest.Key<*>, Any>()
105             aeMode?.let { map.put(CaptureRequest.CONTROL_AE_MODE, it.value) }
106             afMode?.let { map.put(CaptureRequest.CONTROL_AF_MODE, it.value) }
107             awbMode?.let { map.put(CaptureRequest.CONTROL_AWB_MODE, it.value) }
108             flashMode?.let { map.put(CaptureRequest.FLASH_MODE, it.value) }
109             aeRegions?.let { map.put(CaptureRequest.CONTROL_AE_REGIONS, it.toTypedArray()) }
110             afRegions?.let { map.put(CaptureRequest.CONTROL_AF_REGIONS, it.toTypedArray()) }
111             awbRegions?.let { map.put(CaptureRequest.CONTROL_AWB_REGIONS, it.toTypedArray()) }
112             aeLock?.let { map.put(CaptureRequest.CONTROL_AE_LOCK, it) }
113             awbLock?.let { map.put(CaptureRequest.CONTROL_AWB_LOCK, it) }
114             return map
115         }
116     }
117 
writeTonull118     fun writeTo(map: MutableMap<Any, Any?>) {
119         synchronized(this) {
120             aeMode?.let { map[CaptureRequest.CONTROL_AE_MODE] = it.value }
121             afMode?.let { map[CaptureRequest.CONTROL_AF_MODE] = it.value }
122             awbMode?.let { map[CaptureRequest.CONTROL_AWB_MODE] = it.value }
123             flashMode?.let { map[CaptureRequest.FLASH_MODE] = it.value }
124             aeRegions?.let { map[CaptureRequest.CONTROL_AE_REGIONS] = it.toTypedArray() }
125             afRegions?.let { map[CaptureRequest.CONTROL_AF_REGIONS] = it.toTypedArray() }
126             awbRegions?.let { map[CaptureRequest.CONTROL_AWB_REGIONS] = it.toTypedArray() }
127             aeLock?.let { map[CaptureRequest.CONTROL_AE_LOCK] = it }
128             awbLock?.let { map[CaptureRequest.CONTROL_AWB_LOCK] = it }
129         }
130     }
131 }
132