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.compat
18
19 import android.hardware.camera2.CameraAccessException
20 import androidx.camera.camera2.pipe.CameraError
21 import androidx.camera.camera2.pipe.CameraId
22 import androidx.camera.camera2.pipe.core.Log
23 import androidx.camera.camera2.pipe.internal.CameraErrorListener
24
25 /**
26 * Thrown when an operation cannot be executed because underlying object is closed or in an unusable
27 * state.
28 */
29 internal class ObjectUnavailableException(e: Throwable) : Exception(e)
30
31 /** Catch specific exceptions that are not normally thrown, log them, then rethrow. */
32 @Throws(ObjectUnavailableException::class)
catchAndReportCameraExceptionsnull33 internal inline fun <T> catchAndReportCameraExceptions(
34 cameraId: CameraId,
35 cameraErrorListener: CameraErrorListener,
36 crossinline block: () -> T
37 ): T? {
38 // Camera2 has, at different points in time, thrown a large number of checked and/or
39 // unchecked exceptions under different circumstances that are not listed in the
40 // documentation. This method catches and recasts these exceptions into a common exception
41 // type.
42 //
43 // Specific examples:
44 // * Some exceptions (such as IllegalArgumentException) can happen if a surface is destroyed
45 // out of band during configuration.
46 // * Some exceptions (such as IllegalStateException) can be thrown but are not reported as
47 // being thrown by various methods on some versions of the OS.
48 // * Some exceptions (such as SecurityException) can happen even when the application has
49 // permission to access the camera but a higher priority or security sensitive service is
50 // currently using the camera.
51 // * Some exceptions (such as UnsupportedOperationException) can be thrown on some versions
52 // of the OS (b/28617016)
53 try {
54 return block()
55 } catch (e: Exception) {
56 Log.warn { "Unexpected error: " + e.message }
57 when (e) {
58 is CameraAccessException -> {
59 cameraErrorListener.onCameraError(
60 cameraId,
61 CameraError.from(e),
62 // CameraAccessException indicates the task failed because the camera is
63 // unavailable, such as when the camera is in use or disconnected. Such errors
64 // can be recovered when the camera becomes available.
65 willAttemptRetry = true,
66 )
67 return null
68 }
69 is IllegalArgumentException,
70 is IllegalStateException,
71 is SecurityException,
72 is UnsupportedOperationException,
73 is NullPointerException -> {
74 cameraErrorListener.onCameraError(
75 cameraId,
76 CameraError.ERROR_GRAPH_CONFIG,
77 willAttemptRetry = false
78 )
79 return null
80 }
81 else -> throw e
82 }
83 }
84 }
85