1 /*
2 * Copyright 2019 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 // Camera 1 API is deprecated, suppress warnings as Antelope expressly tests it
18 @file:Suppress("deprecation")
19
20 package androidx.camera.integration.antelope.cameracontrollers
21
22 import android.hardware.Camera
23 import android.util.Size
24 import androidx.camera.integration.antelope.CameraParams
25 import androidx.camera.integration.antelope.CompareSizesByArea
26 import androidx.camera.integration.antelope.FocusMode
27 import androidx.camera.integration.antelope.ImageCaptureSize
28 import androidx.camera.integration.antelope.MainActivity
29 import androidx.camera.integration.antelope.MainActivity.Companion.logd
30 import androidx.camera.integration.antelope.PrefHelper
31 import androidx.camera.integration.antelope.TestConfig
32 import androidx.camera.integration.antelope.TestType
33 import androidx.camera.integration.antelope.testEnded
34 import androidx.camera.integration.antelope.writeFile
35 import java.util.Collections
36
37 internal var camera1: Camera? = null
38
39 /**
40 * Opens the camera using the Camera1 API and measures the open time synchronously. For init tests,
41 * this is the only measurement needed so end the test. Otherwise, move on to open the camera
42 * preview.
43 */
camera1OpenCameranull44 fun camera1OpenCamera(activity: MainActivity, params: CameraParams, testConfig: TestConfig) {
45 try {
46 logd("openCamera: " + params.id)
47 params.isOpen = true
48 params.timer.openStart = System.currentTimeMillis()
49
50 logd("Camera1Switch Open camera: " + testConfig.switchTestCurrentCamera.toInt())
51
52 if (
53 (testConfig.currentRunningTest == TestType.SWITCH_CAMERA) ||
54 (testConfig.currentRunningTest == TestType.MULTI_SWITCH)
55 )
56 camera1 = Camera.open(testConfig.switchTestCurrentCamera.toInt())
57 else camera1 = Camera.open(testConfig.camera.toInt())
58
59 params.timer.openEnd = System.currentTimeMillis()
60
61 // Due to the synchronous nature of Camera1, set up Camera1 specific parameters here
62 val camera1Params: Camera.Parameters? = camera1?.parameters
63 params.cam1AFSupported =
64 camera1Params?.supportedFocusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) ?: false
65
66 when (testConfig.currentRunningTest) {
67 TestType.INIT -> {
68 // Camera opened, we're done
69 testEnded(activity, params, testConfig)
70 }
71 else -> {
72 startCamera1Preview(activity, params, testConfig)
73 }
74 }
75 } catch (e: Exception) {
76 logd("camera1OpenCamera exception: " + params.id + ". Error: " + e.printStackTrace())
77 camera1 = null
78 }
79 }
80
81 /**
82 * Begin the preview using the Camera 1 API and synchronously measure the time to begin the stream.
83 */
startCamera1Previewnull84 fun startCamera1Preview(activity: MainActivity, params: CameraParams, testConfig: TestConfig) {
85 val camera1Params: Camera.Parameters? = camera1?.parameters
86
87 params.cam1AFSupported =
88 camera1Params?.supportedFocusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) ?: false
89
90 // Get Camera1 image capture sizes
91 // Cannot be done this before the camera is device opened
92 val cam1Sizes = camera1Params?.getSupportedPictureSizes()
93 if (null != cam1Sizes) {
94 val saneSizes: ArrayList<Size> = ArrayList()
95
96 for (size in cam1Sizes) {
97 saneSizes.add(Size(size.width, size.height))
98 }
99
100 params.cam1MaxSize = Collections.max(saneSizes, CompareSizesByArea())
101 params.cam1MinSize = Collections.min(saneSizes, CompareSizesByArea())
102 }
103
104 if (ImageCaptureSize.MIN == testConfig.imageCaptureSize)
105 camera1Params?.setPictureSize(params.cam1MinSize.width, params.cam1MinSize.height)
106 else camera1Params?.setPictureSize(params.cam1MaxSize.width, params.cam1MaxSize.height)
107
108 if (params.cam1AFSupported) {
109 if (FocusMode.CONTINUOUS == testConfig.focusMode)
110 camera1Params?.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
111 else camera1Params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO
112 } else {
113 camera1Params?.focusMode = Camera.Parameters.FOCUS_MODE_FIXED
114 }
115
116 // After changing camera parameters, set them
117 camera1?.parameters = camera1Params
118
119 logd("startCamera1Preview: starting Camera1 preview.")
120
121 params.isPreviewing = true
122 params.timer.previewStart = System.currentTimeMillis()
123 camera1?.startPreview()
124 camera1?.setPreviewDisplay(params.previewSurfaceView?.holder)
125 params.timer.previewEnd = System.currentTimeMillis()
126
127 when (testConfig.currentRunningTest) {
128 TestType.PREVIEW -> {
129 testConfig.testFinished = true
130 closePreviewAndCamera(activity, params, testConfig)
131 }
132 TestType.SWITCH_CAMERA,
133 TestType.MULTI_SWITCH -> {
134 logd("Camera1Switch preview running:")
135 if (testConfig.switchTestCurrentCamera == testConfig.switchTestCameras.get(0)) {
136 if (testConfig.testFinished) {
137 logd("Camera1Switch preview. On 1st camera, test finished. Closing 1st camera")
138 params.timer.switchToFirstEnd = System.currentTimeMillis()
139 Thread.sleep(PrefHelper.getPreviewBuffer(activity)) // Let preview run
140 closePreviewAndCamera(activity, params, testConfig)
141 } else {
142 logd("Camera1Switch preview. On 1st camera, Closing 1st camera, then open 2nd")
143 Thread.sleep(PrefHelper.getPreviewBuffer(activity)) // Let preview run
144 params.timer.switchToSecondStart = System.currentTimeMillis()
145 closePreviewAndCamera(activity, params, testConfig)
146 }
147 } else {
148 logd(
149 "Camera1Switch preview. On 2nd camera. Closing, ready to open first 1st " +
150 "camera"
151 )
152 params.timer.switchToSecondEnd = System.currentTimeMillis()
153 Thread.sleep(PrefHelper.getPreviewBuffer(activity)) // Let preview run
154 params.timer.switchToFirstStart = System.currentTimeMillis()
155 closePreviewAndCamera(activity, params, testConfig)
156 }
157 }
158 TestType.NONE -> {
159 closeAllCameras(activity, testConfig)
160 }
161 else -> {
162 camera1TakePicturePrep(activity, params, testConfig)
163 }
164 }
165 }
166
167 /**
168 * Set up timers and focus mode for taking a picture with the Camera 1 API. If auto-focus is
169 * requested, begin the auto-focus timer and asynchronously begin the auto-focus routine.
170 */
camera1TakePicturePrepnull171 fun camera1TakePicturePrep(activity: MainActivity, params: CameraParams, testConfig: TestConfig) {
172 if (params.timer.isFirstPhoto) {
173 logd(
174 "camera1TakePicturePrep: 1st photo in multi-chain test. Pausing for " +
175 PrefHelper.getPreviewBuffer(activity) +
176 "ms to let preview run."
177 )
178 params.timer.previewFillStart = System.currentTimeMillis()
179 Thread.sleep(PrefHelper.getPreviewBuffer(activity))
180 params.timer.previewFillEnd = System.currentTimeMillis()
181 params.timer.isFirstPhoto = false
182 }
183
184 params.timer.captureStart = System.currentTimeMillis()
185
186 if (params.cam1AFSupported && FocusMode.AUTO == testConfig.focusMode) {
187 MainActivity.logd("camera1TakePicturePrep: starting autofocus.")
188 params.timer.autofocusStart = System.currentTimeMillis()
189 camera1?.autoFocus(Camera1AutofocusCallback(activity, params, testConfig))
190 } else {
191 camera1TakePicture(activity, params, testConfig)
192 }
193 }
194
195 /** Initiate the capture request */
camera1TakePicturenull196 fun camera1TakePicture(activity: MainActivity, params: CameraParams, testConfig: TestConfig) {
197 val camera1JpegCallback = Camera1PictureCallback(activity, params, testConfig)
198
199 try {
200 MainActivity.logd("camera1TakePicture: capture start. ")
201 camera1?.takePicture(null, null, camera1JpegCallback)
202 } catch (e: RuntimeException) {
203 MainActivity.logd("camera1TakePicture: runtime exception: " + e.printStackTrace())
204 }
205 }
206
207 /** Close preview stream and camera device. If this is a switch test, begin the next step */
camera1CloseCameranull208 fun camera1CloseCamera(activity: MainActivity, params: CameraParams?, testConfig: TestConfig) {
209 if (params == null) return
210
211 if (params.isPreviewing) {
212 params.timer.previewCloseStart = System.currentTimeMillis()
213 camera1?.stopPreview()
214 params.timer.previewCloseEnd = System.currentTimeMillis()
215 params.isPreviewing = false
216 }
217
218 params.timer.cameraCloseStart = System.currentTimeMillis()
219 camera1?.release()
220 params.timer.cameraCloseEnd = System.currentTimeMillis()
221 params.isOpen = false
222
223 logd("Camera 1 Close camera: camera released.")
224
225 if (testConfig.testFinished) {
226 logd("Camera 1 Close camera: Test finished, returning")
227 testEnded(activity, params, testConfig)
228 return
229 }
230
231 when (testConfig.currentRunningTest) {
232 TestType.SWITCH_CAMERA,
233 TestType.MULTI_SWITCH -> {
234 logd("Camera1Switch Close camera")
235 // First camera closed, now start the second
236 if (testConfig.switchTestCurrentCamera == testConfig.switchTestCameras.get(0)) {
237 testConfig.switchTestCurrentCamera = testConfig.switchTestCameras.get(1)
238 logd("Camera1Switch Close camera 1st camera is closed, opening the second")
239 camera1OpenCamera(activity, params, testConfig)
240 }
241
242 // Second camera closed, now start the first
243 else if (testConfig.switchTestCurrentCamera == testConfig.switchTestCameras.get(1)) {
244 logd("Camera1Switch Close camera 2nd camera is closed, opening the first")
245 testConfig.switchTestCurrentCamera = testConfig.switchTestCameras.get(0)
246 testConfig.testFinished = true
247 camera1OpenCamera(activity, params, testConfig)
248 }
249 }
250 else -> {
251 Unit // no-op
252 }
253 }
254 }
255
256 /** Auto-focus is complete, record the elapsed time and request the capture */
257 class Camera1AutofocusCallback
258 internal constructor(
259 internal val activity: MainActivity,
260 internal val params: CameraParams,
261 internal val testConfig: TestConfig
262 ) : Camera.AutoFocusCallback {
263
264 @Suppress("OVERRIDE_DEPRECATION") // b/407496822
onAutoFocusnull265 override fun onAutoFocus(p0: Boolean, p1: Camera?) {
266 MainActivity.logd("camera1AutofocusCallback: autofocus complete.")
267 params.timer.autofocusEnd = System.currentTimeMillis()
268 camera1TakePicture(activity, params, testConfig)
269 }
270 }
271
272 /**
273 * Image capture has completed. Record the time taken, synchronously write file to disk and measure
274 * the time required. This test run is finished, call to finalize test or continue the test run.
275 */
276 class Camera1PictureCallback
277 internal constructor(
278 internal val activity: MainActivity,
279 internal val params: CameraParams,
280 internal val testConfig: TestConfig
281 ) : Camera.PictureCallback {
282
283 @Suppress("OVERRIDE_DEPRECATION") // b/407496822
onPictureTakennull284 override fun onPictureTaken(bytes: ByteArray?, p1: Camera?) {
285
286 params.timer.captureEnd = System.currentTimeMillis()
287
288 // With the Camera1 API, calling takePicture() stops the preview. In order to make sure the
289 // close timings are comparable across APIs, restart it here.
290 camera1?.startPreview()
291
292 logd("in Camera1PictureCallback onPictureTaken")
293
294 params.timer.imageReaderStart = System.currentTimeMillis()
295 params.timer.imageReaderEnd = System.currentTimeMillis()
296 params.timer.imageSaveStart = System.currentTimeMillis()
297
298 if (null != bytes) writeFile(activity, bytes)
299
300 params.timer.imageSaveEnd = System.currentTimeMillis()
301
302 testConfig.testFinished = true
303 closePreviewAndCamera(activity, params, testConfig)
304 }
305 }
306