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.params.MeteringRectangle
20 import androidx.camera.camera2.pipe.AeMode
21 import androidx.camera.camera2.pipe.AfMode
22 import androidx.camera.camera2.pipe.AwbMode
23 import androidx.camera.camera2.pipe.CameraGraph
24 import androidx.camera.camera2.pipe.FrameCapture
25 import androidx.camera.camera2.pipe.FrameMetadata
26 import androidx.camera.camera2.pipe.Lock3ABehavior
27 import androidx.camera.camera2.pipe.Request
28 import androidx.camera.camera2.pipe.Result3A
29 import androidx.camera.camera2.pipe.core.Token
30 import androidx.camera.camera2.pipe.internal.CameraGraphParametersImpl
31 import androidx.camera.camera2.pipe.internal.FrameCaptureQueue
32 import kotlinx.atomicfu.atomic
33 import kotlinx.coroutines.Deferred
34 
35 internal val cameraGraphSessionIds = atomic(0)
36 
37 internal class CameraGraphSessionImpl(
38     private val token: Token,
39     private val graphProcessor: GraphProcessor,
40     private val controller3A: Controller3A,
41     private val frameCaptureQueue: FrameCaptureQueue,
42     private val parameters: CameraGraphParametersImpl
43 ) : CameraGraph.Session {
44     private val debugId = cameraGraphSessionIds.incrementAndGet()
45 
submitnull46     override fun submit(request: Request) {
47         check(!token.released) { "Cannot call submit on $this after close." }
48         graphProcessor.submit(request)
49     }
50 
submitnull51     override fun submit(requests: List<Request>) {
52         check(!token.released) { "Cannot call submit on $this after close." }
53         check(requests.isNotEmpty()) { "Cannot call submit with an empty list of Requests!" }
54         graphProcessor.submit(requests)
55     }
56 
capturenull57     override fun capture(request: Request): FrameCapture {
58         val frameCapture = frameCaptureQueue.enqueue(request)
59         submit(request)
60         return frameCapture
61     }
62 
capturenull63     override fun capture(requests: List<Request>): List<FrameCapture> {
64         val frameCaptures = frameCaptureQueue.enqueue(requests)
65         submit(requests)
66         return frameCaptures
67     }
68 
startRepeatingnull69     override fun startRepeating(request: Request) {
70         check(!token.released) { "Cannot call startRepeating on $this after close." }
71         graphProcessor.repeatingRequest = request
72     }
73 
abortnull74     override fun abort() {
75         check(!token.released) { "Cannot call abort on $this after close." }
76         graphProcessor.abort()
77     }
78 
stopRepeatingnull79     override fun stopRepeating() {
80         check(!token.released) { "Cannot call stopRepeating on $this after close." }
81         graphProcessor.repeatingRequest = null
82     }
83 
closenull84     override fun close() {
85         val unappliedParameters = parameters.fetchUpdatedParameters()
86         if (unappliedParameters != null) {
87             graphProcessor.updateGraphParameters(unappliedParameters)
88         }
89         token.release()
90     }
91 
update3Anull92     override fun update3A(
93         aeMode: AeMode?,
94         afMode: AfMode?,
95         awbMode: AwbMode?,
96         aeRegions: List<MeteringRectangle>?,
97         afRegions: List<MeteringRectangle>?,
98         awbRegions: List<MeteringRectangle>?
99     ): Deferred<Result3A> {
100         check(!token.released) { "Cannot call update3A on $this after close." }
101         return controller3A.update3A(
102             aeMode = aeMode,
103             afMode = afMode,
104             awbMode = awbMode,
105             aeRegions = aeRegions,
106             afRegions = afRegions,
107             awbRegions = awbRegions
108         )
109     }
110 
submit3Anull111     override suspend fun submit3A(
112         aeMode: AeMode?,
113         afMode: AfMode?,
114         awbMode: AwbMode?,
115         aeRegions: List<MeteringRectangle>?,
116         afRegions: List<MeteringRectangle>?,
117         awbRegions: List<MeteringRectangle>?
118     ): Deferred<Result3A> {
119         check(!token.released) { "Cannot call submit3A on $this after close." }
120         return controller3A.submit3A(aeMode, afMode, awbMode, aeRegions, afRegions, awbRegions)
121     }
122 
setTorchOnnull123     override fun setTorchOn(): Deferred<Result3A> {
124         check(!token.released) { "Cannot call setTorchOn on $this after close." }
125         // TODO(sushilnath): First check whether the camera device has a flash unit. Ref:
126         // https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#FLASH_INFO_AVAILABLE
127         return controller3A.setTorchOn()
128     }
129 
setTorchOffnull130     override fun setTorchOff(aeMode: AeMode?): Deferred<Result3A> {
131         check(!token.released) { "Cannot call setTorchOff on $this after close." }
132         return controller3A.setTorchOff(aeMode)
133     }
134 
lock3Anull135     override suspend fun lock3A(
136         aeMode: AeMode?,
137         afMode: AfMode?,
138         awbMode: AwbMode?,
139         aeRegions: List<MeteringRectangle>?,
140         afRegions: List<MeteringRectangle>?,
141         awbRegions: List<MeteringRectangle>?,
142         aeLockBehavior: Lock3ABehavior?,
143         afLockBehavior: Lock3ABehavior?,
144         awbLockBehavior: Lock3ABehavior?,
145         afTriggerStartAeMode: AeMode?,
146         convergedCondition: ((FrameMetadata) -> Boolean)?,
147         lockedCondition: ((FrameMetadata) -> Boolean)?,
148         frameLimit: Int,
149         convergedTimeLimitNs: Long,
150         lockedTimeLimitNs: Long
151     ): Deferred<Result3A> {
152         check(!token.released) { "Cannot call lock3A on $this after close." }
153         // TODO(sushilnath): check if the device or the current mode supports lock for each of
154         // ae, af and awb respectively. If not supported return an exception or return early with
155         // the right status code.
156         return controller3A.lock3A(
157             aeRegions,
158             afRegions,
159             awbRegions,
160             aeLockBehavior,
161             afLockBehavior,
162             awbLockBehavior,
163             afTriggerStartAeMode,
164             convergedCondition,
165             lockedCondition,
166             frameLimit,
167             convergedTimeLimitNs,
168             lockedTimeLimitNs
169         )
170     }
171 
unlock3Anull172     override suspend fun unlock3A(
173         ae: Boolean?,
174         af: Boolean?,
175         awb: Boolean?,
176         unlockedCondition: ((FrameMetadata) -> Boolean)?,
177         frameLimit: Int,
178         timeLimitNs: Long
179     ): Deferred<Result3A> {
180         check(!token.released) { "Cannot call unlock3A on $this after close." }
181         return controller3A.unlock3A(ae, af, awb, unlockedCondition, frameLimit, timeLimitNs)
182     }
183 
lock3AForCapturenull184     override suspend fun lock3AForCapture(
185         lockedCondition: ((FrameMetadata) -> Boolean)?,
186         frameLimit: Int,
187         timeLimitNs: Long
188     ): Deferred<Result3A> {
189         check(!token.released) { "Cannot call lock3AForCapture on $this after close." }
190         return controller3A.lock3AForCapture(lockedCondition, frameLimit, timeLimitNs)
191     }
192 
lock3AForCapturenull193     override suspend fun lock3AForCapture(
194         triggerAf: Boolean,
195         waitForAwb: Boolean,
196         frameLimit: Int,
197         timeLimitNs: Long
198     ): Deferred<Result3A> {
199         check(!token.released) { "Cannot call lock3AForCapture on $this after close." }
200         return controller3A.lock3AForCapture(triggerAf, waitForAwb, frameLimit, timeLimitNs)
201     }
202 
unlock3APostCapturenull203     override suspend fun unlock3APostCapture(cancelAf: Boolean): Deferred<Result3A> {
204         check(!token.released) { "Cannot call unlock3APostCapture on $this after close." }
205         return controller3A.unlock3APostCapture(cancelAf)
206     }
207 
toStringnull208     override fun toString(): String = "CameraGraph.Session-$debugId"
209 }
210