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.integration.extensions
18 
19 import android.hardware.camera2.CameraCaptureSession
20 import android.hardware.camera2.CameraExtensionSession
21 import android.hardware.camera2.CameraMetadata.CONTROL_AF_TRIGGER_CANCEL
22 import android.hardware.camera2.CameraMetadata.CONTROL_AF_TRIGGER_IDLE
23 import android.hardware.camera2.CaptureRequest
24 import android.hardware.camera2.CaptureResult
25 import android.hardware.camera2.TotalCaptureResult
26 import android.hardware.camera2.params.MeteringRectangle
27 import android.util.Log
28 import androidx.annotation.RequiresApi
29 import java.util.concurrent.Executors
30 import java.util.concurrent.ScheduledExecutorService
31 import java.util.concurrent.ScheduledFuture
32 import java.util.concurrent.TimeUnit
33 
34 val EMPTY_RECTANGLES = arrayOfNulls<MeteringRectangle>(0)
35 
36 private const val TAG = "FocusMeteringControl"
37 private const val AUTO_FOCUS_TIMEOUT_DURATION_MS = 5000L
38 
39 /**
40  * A class to manage focus-metering related operations. This class will help to monitor whether the
41  * state is locked or not and then make the AF-Trigger become to idle or cancel state.
42  */
43 @RequiresApi(31)
44 class FocusMeteringControl(
45     private val startAfTriggerImpl: (Array<MeteringRectangle?>) -> Unit,
46     private val cancelAfTriggerImpl: (Int) -> Unit
47 ) {
48 
49     private val scheduler: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
50     private var currentAfState: Int = CaptureResult.CONTROL_AF_STATE_INACTIVE
51     private var autoCancelHandle: ScheduledFuture<*>? = null
52     private var autoFocusTimeoutHandle: ScheduledFuture<*>? = null
53     private var focusTimeoutCounter: Long = 0
54     private var isAutoFocusCompleted: Boolean = true
55 
56     private val captureCallbackExtensionMode =
57         object : CameraExtensionSession.ExtensionCaptureCallback() {
onCaptureResultAvailablenull58             override fun onCaptureResultAvailable(
59                 session: CameraExtensionSession,
60                 request: CaptureRequest,
61                 result: TotalCaptureResult
62             ) {
63                 result.get(CaptureResult.CONTROL_AF_STATE)?.let { handleCaptureResultForAf(it) }
64             }
65         }
66 
67     private val captureCallbackNormalMode =
68         object : CameraCaptureSession.CaptureCallback() {
onCaptureCompletednull69             override fun onCaptureCompleted(
70                 session: CameraCaptureSession,
71                 request: CaptureRequest,
72                 result: TotalCaptureResult
73             ) {
74                 result.get(CaptureResult.CONTROL_AF_STATE)?.let { handleCaptureResultForAf(it) }
75             }
76         }
77 
handleCaptureResultForAfnull78     private fun handleCaptureResultForAf(afState: Int?) {
79         if (isAutoFocusCompleted) {
80             return
81         }
82 
83         if (afState == null) {
84             Log.e(TAG, "afState == null")
85             // set isAutoFocusCompleted to true when camera does not support AF_AUTO.
86             isAutoFocusCompleted = true
87         } else if (currentAfState == CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN) {
88             if (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED) {
89                 Log.d(TAG, "afState == CONTROL_AF_STATE_FOCUSED_LOCKED")
90                 isAutoFocusCompleted = true
91             } else if (afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
92                 Log.d(TAG, "afState == CONTROL_AF_STATE_NOT_FOCUSED_LOCKED")
93                 isAutoFocusCompleted = true
94             }
95         }
96 
97         // Check 3A regions
98         if (isAutoFocusCompleted) {
99             clearAutoFocusTimeoutHandle()
100             Log.d(TAG, "cancelAfTrigger: CONTROL_AF_TRIGGER_IDLE")
101             cancelAfTriggerImpl.invoke(CONTROL_AF_TRIGGER_IDLE)
102         }
103 
104         if (currentAfState != afState && afState != null) {
105             currentAfState = afState
106         }
107     }
108 
updateMeteringRectanglesnull109     fun updateMeteringRectangles(meteringRectangles: Array<MeteringRectangle?>) {
110         clearAutoFocusTimeoutHandle()
111         isAutoFocusCompleted = false
112         val timeoutId: Long = ++focusTimeoutCounter
113         autoFocusTimeoutHandle =
114             scheduler.schedule(
115                 {
116                     Log.d(TAG, "cancelAfTrigger: CONTROL_AF_TRIGGER_CANCEL")
117                     cancelAfTriggerImpl.invoke(CONTROL_AF_TRIGGER_CANCEL)
118                     if (timeoutId == focusTimeoutCounter) {
119                         isAutoFocusCompleted = true
120                     }
121                 },
122                 AUTO_FOCUS_TIMEOUT_DURATION_MS,
123                 TimeUnit.MILLISECONDS
124             )
125         currentAfState = CaptureResult.CONTROL_AF_STATE_INACTIVE
126         startAfTriggerImpl.invoke(meteringRectangles)
127     }
128 
getCaptureCallbacknull129     fun getCaptureCallback(extensionEnabled: Boolean): Any =
130         if (extensionEnabled) {
131             captureCallbackExtensionMode
132         } else {
133             captureCallbackNormalMode
134         }
135 
clearAutoFocusTimeoutHandlenull136     private fun clearAutoFocusTimeoutHandle() {
137         autoFocusTimeoutHandle?.let {
138             it.cancel(/* mayInterruptIfRunning= */ true)
139             autoCancelHandle = null
140         }
141     }
142 }
143