1 /*
<lambda>null2  * 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.compat
18 
19 import android.content.Context
20 import android.hardware.camera2.CameraAccessException
21 import android.hardware.camera2.CameraCaptureSession
22 import android.hardware.camera2.CameraCharacteristics
23 import android.hardware.camera2.CameraDevice
24 import android.hardware.camera2.CameraExtensionCharacteristics
25 import android.hardware.camera2.CameraExtensionSession
26 import android.hardware.camera2.CameraManager
27 import android.hardware.camera2.CaptureRequest
28 import android.hardware.camera2.CaptureResult
29 import android.hardware.camera2.TotalCaptureResult
30 import android.hardware.camera2.params.ExtensionSessionConfiguration
31 import android.hardware.camera2.params.InputConfiguration
32 import android.hardware.camera2.params.MultiResolutionStreamInfo
33 import android.hardware.camera2.params.OutputConfiguration
34 import android.hardware.camera2.params.SessionConfiguration
35 import android.media.ImageReader
36 import android.media.ImageWriter
37 import android.os.Handler
38 import android.util.Size
39 import android.view.Surface
40 import androidx.annotation.RequiresApi
41 import androidx.annotation.RequiresPermission
42 import androidx.camera.camera2.pipe.CameraMetadata
43 import java.util.concurrent.Executor
44 
45 @RequiresApi(23)
46 internal object Api23Compat {
47     @JvmStatic
48     @Throws(CameraAccessException::class)
49     @Suppress("deprecation")
50     fun createReprocessableCaptureSession(
51         cameraDevice: CameraDevice,
52         inputConfig: InputConfiguration,
53         outputs: List<Surface>,
54         callback: CameraCaptureSession.StateCallback,
55         handler: Handler?
56     ) {
57         cameraDevice.createReprocessableCaptureSession(inputConfig, outputs, callback, handler)
58     }
59 
60     @JvmStatic
61     @Throws(CameraAccessException::class)
62     @Suppress("deprecation")
63     fun createConstrainedHighSpeedCaptureSession(
64         cameraDevice: CameraDevice,
65         outputs: List<Surface>,
66         stateCallback: CameraCaptureSession.StateCallback,
67         handler: Handler?
68     ) {
69         cameraDevice.createConstrainedHighSpeedCaptureSession(outputs, stateCallback, handler)
70     }
71 
72     @JvmStatic
73     @Throws(CameraAccessException::class)
74     fun createReprocessCaptureRequest(
75         cameraDevice: CameraDevice,
76         inputResult: TotalCaptureResult,
77     ): CaptureRequest.Builder {
78         return cameraDevice.createReprocessCaptureRequest(inputResult)
79     }
80 
81     @JvmStatic
82     fun isReprocessable(cameraCaptureSession: CameraCaptureSession): Boolean {
83         return cameraCaptureSession.isReprocessable
84     }
85 
86     @JvmStatic
87     fun getInputSurface(cameraCaptureSession: CameraCaptureSession): Surface? {
88         return cameraCaptureSession.inputSurface
89     }
90 
91     @JvmStatic
92     fun newInputConfiguration(width: Int, height: Int, format: Int): InputConfiguration {
93         return InputConfiguration(width, height, format)
94     }
95 
96     @JvmStatic
97     fun checkSelfPermission(context: Context, permission: String): Int {
98         return context.checkSelfPermission(permission)
99     }
100 }
101 
102 @RequiresApi(24)
103 internal object Api24Compat {
104     @JvmStatic
105     @Throws(CameraAccessException::class)
106     @Suppress("deprecation")
createCaptureSessionByOutputConfigurationsnull107     fun createCaptureSessionByOutputConfigurations(
108         cameraDevice: CameraDevice,
109         outputConfig: List<OutputConfiguration?>,
110         stateCallback: CameraCaptureSession.StateCallback,
111         handler: Handler?
112     ) {
113         cameraDevice.createCaptureSessionByOutputConfigurations(
114             outputConfig,
115             stateCallback,
116             handler
117         )
118     }
119 
120     @JvmStatic
121     @Throws(CameraAccessException::class)
122     @Suppress("deprecation")
createReprocessableCaptureSessionByConfigurationsnull123     fun createReprocessableCaptureSessionByConfigurations(
124         cameraDevice: CameraDevice,
125         inputConfig: InputConfiguration,
126         outputs: List<OutputConfiguration?>,
127         stateCallback: CameraCaptureSession.StateCallback,
128         handler: Handler?
129     ) {
130         cameraDevice.createReprocessableCaptureSessionByConfigurations(
131             inputConfig,
132             outputs,
133             stateCallback,
134             handler
135         )
136     }
137 
138     @JvmStatic
getSurfaceGroupIdnull139     fun getSurfaceGroupId(outputConfiguration: OutputConfiguration): Int {
140         return outputConfiguration.surfaceGroupId
141     }
142 }
143 
144 @RequiresApi(26)
145 internal object Api26Compat {
146     @JvmStatic
147     @Throws(CameraAccessException::class)
finalizeOutputConfigurationsnull148     fun finalizeOutputConfigurations(
149         cameraCaptureSession: CameraCaptureSession,
150         outputConfiguration: List<OutputConfiguration?>
151     ) {
152         return cameraCaptureSession.finalizeOutputConfigurations(outputConfiguration)
153     }
154 
155     @JvmStatic
newOutputConfigurationnull156     fun newOutputConfiguration(size: Size, klass: Class<*>): OutputConfiguration {
157         return OutputConfiguration(size, klass)
158     }
159 
160     @JvmStatic
enableSurfaceSharingnull161     fun enableSurfaceSharing(outputConfig: OutputConfiguration) {
162         outputConfig.enableSurfaceSharing()
163     }
164 
165     @JvmStatic
getSurfacesnull166     fun getSurfaces(outputConfig: OutputConfiguration): List<Surface> {
167         return outputConfig.surfaces
168     }
169 
170     @JvmStatic
addSurfacesnull171     fun addSurfaces(outputConfig: OutputConfiguration, surface: Surface) {
172         return outputConfig.addSurface(surface)
173     }
174 
175     @JvmStatic
onCaptureQueueEmptynull176     fun onCaptureQueueEmpty(
177         interopSessionStateCallback: CameraCaptureSession.StateCallback?,
178         session: CameraCaptureSession,
179     ) {
180         interopSessionStateCallback?.onCaptureQueueEmpty(session)
181     }
182 }
183 
184 @RequiresApi(28)
185 @Suppress("DEPRECATION")
186 internal object Api28Compat {
187     @JvmStatic
188     @Throws(CameraAccessException::class)
createCaptureSessionnull189     fun createCaptureSession(
190         cameraDevice: CameraDevice,
191         sessionConfig: SessionConfiguration,
192     ) {
193         cameraDevice.createCaptureSession(sessionConfig)
194     }
195 
196     @JvmStatic
getAvailablePhysicalCameraRequestKeysnull197     fun getAvailablePhysicalCameraRequestKeys(
198         cameraCharacteristics: CameraCharacteristics
199     ): List<CaptureRequest.Key<*>>? {
200         return cameraCharacteristics.availablePhysicalCameraRequestKeys
201     }
202 
203     @JvmStatic
getAvailableSessionKeysnull204     fun getAvailableSessionKeys(
205         cameraCharacteristics: CameraCharacteristics
206     ): List<CaptureRequest.Key<*>>? {
207         return cameraCharacteristics.availableSessionKeys
208     }
209 
210     @JvmStatic
getPhysicalCameraIdsnull211     fun getPhysicalCameraIds(cameraCharacteristics: CameraCharacteristics): Set<String> {
212         return cameraCharacteristics.physicalCameraIds
213     }
214 
215     @JvmStatic
getPhysicalCaptureResultsnull216     fun getPhysicalCaptureResults(
217         totalCaptureResult: TotalCaptureResult
218     ): Map<String, CaptureResult>? {
219         return totalCaptureResult.physicalCameraResults
220     }
221 
222     @JvmStatic
newSessionConfigurationnull223     fun newSessionConfiguration(
224         sessionType: Int,
225         outputs: List<OutputConfiguration?>,
226         executor: Executor,
227         stateCallback: CameraCaptureSession.StateCallback
228     ): SessionConfiguration {
229         return SessionConfiguration(sessionType, outputs, executor, stateCallback)
230     }
231 
232     @JvmStatic
setInputConfigurationnull233     fun setInputConfiguration(
234         sessionConfig: SessionConfiguration,
235         inputConfig: InputConfiguration
236     ) {
237         sessionConfig.inputConfiguration = inputConfig
238     }
239 
240     @JvmStatic
setSessionParametersnull241     fun setSessionParameters(sessionConfig: SessionConfiguration, params: CaptureRequest) {
242         sessionConfig.sessionParameters = params
243     }
244 
245     @JvmStatic
getMaxSharedSurfaceCountnull246     fun getMaxSharedSurfaceCount(outputConfig: OutputConfiguration): Int {
247         return outputConfig.maxSharedSurfaceCount
248     }
249 
250     @JvmStatic
setPhysicalCameraIdnull251     fun setPhysicalCameraId(outputConfig: OutputConfiguration, cameraId: String?) {
252         outputConfig.setPhysicalCameraId(cameraId)
253     }
254 
255     @JvmStatic
removeSurfacenull256     fun removeSurface(outputConfig: OutputConfiguration, surface: Surface) {
257         return outputConfig.removeSurface(surface)
258     }
259 
260     @JvmStatic
261     @Throws(CameraAccessException::class)
262     @RequiresPermission(android.Manifest.permission.CAMERA)
openCameranull263     fun openCamera(
264         cameraManager: CameraManager,
265         cameraId: String,
266         executor: Executor,
267         callback: CameraDevice.StateCallback
268     ) {
269         cameraManager.openCamera(cameraId, executor, callback)
270     }
271 
272     @JvmStatic
registerAvailabilityCallbacknull273     fun registerAvailabilityCallback(
274         cameraManager: CameraManager,
275         executor: Executor,
276         callback: CameraManager.AvailabilityCallback
277     ) {
278         cameraManager.registerAvailabilityCallback(executor, callback)
279     }
280 
281     @JvmStatic
discardFreeBuffersnull282     fun discardFreeBuffers(imageReader: ImageReader) {
283         imageReader.discardFreeBuffers()
284     }
285 }
286 
287 @RequiresApi(29)
288 internal object Api29Compat {
289     @JvmStatic
imageReaderNewInstancenull290     fun imageReaderNewInstance(
291         width: Int,
292         height: Int,
293         format: Int,
294         capacity: Int,
295         usage: Long
296     ): ImageReader {
297         return ImageReader.newInstance(width, height, format, capacity, usage)
298     }
299 
300     @JvmStatic
imageWriterNewInstancenull301     fun imageWriterNewInstance(surface: Surface, maxImages: Int, format: Int): ImageWriter {
302         return ImageWriter.newInstance(surface, maxImages, format)
303     }
304 }
305 
306 @RequiresApi(30)
307 internal object Api30Compat {
308     @JvmStatic
getConcurrentCameraIdsnull309     fun getConcurrentCameraIds(cameraManager: CameraManager): Set<Set<String>> {
310         return cameraManager.concurrentCameraIds
311     }
312 
313     @JvmStatic
getCameraAudioRestrictionnull314     fun getCameraAudioRestriction(cameraDevice: CameraDevice): Int {
315         return cameraDevice.cameraAudioRestriction
316     }
317 
318     @JvmStatic
setCameraAudioRestrictionnull319     fun setCameraAudioRestriction(cameraDevice: CameraDevice, mode: Int) {
320         cameraDevice.cameraAudioRestriction = mode
321     }
322 }
323 
324 @RequiresApi(31)
325 internal object Api31Compat {
326     @JvmStatic
newInputConfigurationnull327     fun newInputConfiguration(
328         inputConfigData: List<InputConfigData>,
329         cameraId: String
330     ): InputConfiguration {
331         check(inputConfigData.isNotEmpty()) {
332             "Call to create InputConfiguration but list of InputConfigData is empty."
333         }
334 
335         if (inputConfigData.size == 1) {
336             val inputData = inputConfigData.first()
337             return InputConfiguration(inputData.width, inputData.height, inputData.format)
338         }
339         val multiResolutionInput =
340             inputConfigData.map { input ->
341                 MultiResolutionStreamInfo(input.width, input.height, cameraId)
342             }
343         return InputConfiguration(multiResolutionInput, inputConfigData.first().format)
344     }
345 
346     @JvmStatic
newMultiResolutionStreamInfonull347     fun newMultiResolutionStreamInfo(
348         streamWidth: Int,
349         streamHeight: Int,
350         physicalCameraId: String
351     ): MultiResolutionStreamInfo {
352         return MultiResolutionStreamInfo(streamWidth, streamHeight, physicalCameraId)
353     }
354 
355     @JvmStatic
getPhysicalCameraTotalResultsnull356     fun getPhysicalCameraTotalResults(
357         totalCaptureResult: TotalCaptureResult
358     ): Map<String, CaptureResult>? {
359         return totalCaptureResult.physicalCameraTotalResults
360     }
361 
362     @JvmStatic
addSensorPixelModeUsednull363     fun addSensorPixelModeUsed(
364         outputConfiguration: OutputConfiguration,
365         sensorPixelMode: Int,
366     ) {
367         outputConfiguration.addSensorPixelModeUsed(sensorPixelMode)
368     }
369 
370     @JvmStatic
createExtensionCaptureSessionnull371     fun createExtensionCaptureSession(
372         cameraDevice: CameraDevice,
373         extensionConfiguration: ExtensionSessionConfiguration
374     ) {
375         cameraDevice.createExtensionSession(extensionConfiguration)
376     }
377 
378     @JvmStatic
getCameraExtensionCharacteristicsnull379     fun getCameraExtensionCharacteristics(
380         cameraManager: CameraManager,
381         cameraId: String
382     ): CameraExtensionCharacteristics = cameraManager.getCameraExtensionCharacteristics(cameraId)
383 
384     @JvmStatic
385     fun newExtensionSessionConfiguration(
386         extensionMode: Int,
387         outputs: List<OutputConfiguration?>,
388         executor: Executor,
389         stateCallback: CameraExtensionSession.StateCallback
390     ): ExtensionSessionConfiguration {
391         return ExtensionSessionConfiguration(extensionMode, outputs, executor, stateCallback)
392     }
393 
394     @JvmStatic
getSupportedExtensionsnull395     fun getSupportedExtensions(
396         extensionCharacteristics: CameraExtensionCharacteristics
397     ): List<Int> = extensionCharacteristics.supportedExtensions
398 
399     @JvmStatic
400     fun getExtensionSupportedSizes(
401         extensionCharacteristics: CameraExtensionCharacteristics,
402         extension: Int,
403         imageFormat: Int
404     ): List<Size> = extensionCharacteristics.getExtensionSupportedSizes(extension, imageFormat)
405 
406     @JvmStatic
407     fun getExtensionSupportedSizes(
408         extensionCharacteristics: CameraExtensionCharacteristics,
409         extension: Int,
410         klass: Class<*>
411     ): List<Size> = extensionCharacteristics.getExtensionSupportedSizes(extension, klass)
412 }
413 
414 @RequiresApi(33)
415 internal object Api33Compat {
416     @JvmStatic
417     fun setDynamicRangeProfile(outputConfig: OutputConfiguration, dynamicRangeProfile: Long) {
418         outputConfig.dynamicRangeProfile = dynamicRangeProfile
419     }
420 
421     @JvmStatic
422     fun getDynamicRangeProfile(outputConfig: OutputConfiguration): Long {
423         return outputConfig.dynamicRangeProfile
424     }
425 
426     @JvmStatic
427     fun setMirrorMode(outputConfig: OutputConfiguration, mirrorMode: Int) {
428         outputConfig.mirrorMode = mirrorMode
429     }
430 
431     @JvmStatic
432     fun getMirrorMode(outputConfig: OutputConfiguration): Int {
433         return outputConfig.mirrorMode
434     }
435 
436     @JvmStatic
437     fun setStreamUseCase(outputConfig: OutputConfiguration, streamUseCase: Long) {
438         outputConfig.streamUseCase = streamUseCase
439     }
440 
441     @JvmStatic
442     fun getAvailableStreamUseCases(cameraMetadata: CameraMetadata): LongArray? {
443         return cameraMetadata[CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES]
444     }
445 
446     @JvmStatic
447     fun getStreamUseCase(outputConfig: OutputConfiguration): Long {
448         return outputConfig.streamUseCase
449     }
450 
451     @JvmStatic
452     fun setTimestampBase(outputConfig: OutputConfiguration, timestampBase: Int) {
453         outputConfig.timestampBase = timestampBase
454     }
455 
456     @JvmStatic
457     fun getTimestampBase(outputConfig: OutputConfiguration): Int {
458         return outputConfig.timestampBase
459     }
460 
461     @JvmStatic
462     fun getAvailableCaptureRequestKeys(
463         extensionCharacteristics: CameraExtensionCharacteristics,
464         extension: Int
465     ): Set<CaptureRequest.Key<Any>> =
466         extensionCharacteristics.getAvailableCaptureRequestKeys(extension)
467 
468     @JvmStatic
469     fun getAvailableCaptureResultKeys(
470         extensionCharacteristics: CameraExtensionCharacteristics,
471         extension: Int
472     ): Set<CaptureResult.Key<Any>> =
473         extensionCharacteristics.getAvailableCaptureResultKeys(extension)
474 
475     @JvmStatic
476     fun newImageReaderFromImageReaderBuilder(
477         width: Int,
478         height: Int,
479         imageFormat: Int? = null,
480         maxImages: Int? = null,
481         usage: Long? = null,
482         defaultDataSpace: Int? = null,
483         defaultHardwareBufferFormat: Int? = null
484     ): ImageReader {
485         return ImageReader.Builder(width, height)
486             .apply {
487                 if (imageFormat != null) setImageFormat(imageFormat)
488                 if (maxImages != null) setMaxImages(maxImages)
489                 if (usage != null) setUsage(usage)
490                 if (defaultDataSpace != null) setDefaultDataSpace(defaultDataSpace)
491                 if (defaultHardwareBufferFormat != null)
492                     setDefaultHardwareBufferFormat(defaultHardwareBufferFormat)
493             }
494             .build()
495     }
496 }
497 
498 @RequiresApi(34)
499 internal object Api34Compat {
500     @JvmStatic
isPostviewAvailablenull501     fun isPostviewAvailable(
502         extensionCharacteristics: CameraExtensionCharacteristics,
503         extension: Int
504     ): Boolean = extensionCharacteristics.isPostviewAvailable(extension)
505 
506     @JvmStatic
507     fun isCaptureProcessProgressAvailable(
508         extensionCharacteristics: CameraExtensionCharacteristics,
509         extension: Int
510     ): Boolean = extensionCharacteristics.isCaptureProcessProgressAvailable(extension)
511 
512     @JvmStatic
513     fun getPostviewSupportedSizes(
514         extensionCharacteristics: CameraExtensionCharacteristics,
515         extension: Int,
516         captureSize: Size,
517         format: Int
518     ): List<Size> =
519         extensionCharacteristics.getPostviewSupportedSizes(extension, captureSize, format)
520 
521     @JvmStatic
522     fun setPostviewOutputConfiguration(
523         extensionSessionConfiguration: ExtensionSessionConfiguration,
524         postviewOutputConfiguration: OutputConfiguration
525     ) {
526         extensionSessionConfiguration.postviewOutputConfiguration = postviewOutputConfiguration
527     }
528 
529     @JvmStatic
isZoomOverrideSupportednull530     fun isZoomOverrideSupported(cameraMetadata: CameraMetadata): Boolean =
531         cameraMetadata[CameraCharacteristics.CONTROL_AVAILABLE_SETTINGS_OVERRIDES]?.contains(
532             android.hardware.camera2.CameraMetadata.CONTROL_SETTINGS_OVERRIDE_ZOOM
533         ) == true
534 }
535 
536 @RequiresApi(35)
537 internal object Api35Compat {
538     @JvmStatic
539     fun isTorchStrengthSupported(cameraMetadata: CameraMetadata): Boolean {
540         val maxLevel = cameraMetadata[CameraCharacteristics.FLASH_TORCH_STRENGTH_MAX_LEVEL]
541         return maxLevel != null && maxLevel > 1
542     }
543 
544     @JvmStatic
545     fun getDefaultTorchStrengthLevel(cameraMetadata: CameraMetadata): Int {
546         val defaultLevel = cameraMetadata[CameraCharacteristics.FLASH_TORCH_STRENGTH_DEFAULT_LEVEL]
547         return defaultLevel ?: 1
548     }
549 
550     @JvmStatic
551     fun getMaxTorchStrengthLevel(cameraMetadata: CameraMetadata): Int {
552         val maxLevel = cameraMetadata[CameraCharacteristics.FLASH_TORCH_STRENGTH_MAX_LEVEL]
553         return maxLevel ?: 1
554     }
555 }
556