1 /*
2  * Copyright (C) 2014 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 android.hardware.camera2.legacy;
18 
19 import android.hardware.ICameraService;
20 import android.os.ServiceSpecificException;
21 import android.util.AndroidException;
22 
23 import static android.system.OsConstants.*;
24 
25 /**
26  * Utility class containing exception handling used solely by the compatibility mode shim.
27  */
28 public class LegacyExceptionUtils {
29     private static final String TAG = "LegacyExceptionUtils";
30 
31     public static final int NO_ERROR = 0;
32     public static final int PERMISSION_DENIED = -EPERM;
33     public static final int ALREADY_EXISTS = -EEXIST;
34     public static final int BAD_VALUE = -EINVAL;
35     public static final int DEAD_OBJECT = -ENOSYS;
36     public static final int INVALID_OPERATION = -EPIPE;
37     public static final int TIMED_OUT = -ETIMEDOUT;
38 
39     /**
40      * Checked exception thrown when a BufferQueue has been abandoned by its consumer.
41      */
42     public static class BufferQueueAbandonedException extends AndroidException {
BufferQueueAbandonedException()43         public BufferQueueAbandonedException () {}
44 
BufferQueueAbandonedException(String name)45         public BufferQueueAbandonedException(String name) {
46             super(name);
47         }
48 
BufferQueueAbandonedException(String name, Throwable cause)49         public BufferQueueAbandonedException(String name, Throwable cause) {
50             super(name, cause);
51         }
52 
BufferQueueAbandonedException(Exception cause)53         public BufferQueueAbandonedException(Exception cause) {
54             super(cause);
55         }
56     }
57 
58     /**
59      * Throw error codes used by legacy device methods as exceptions.
60      *
61      * <p>Non-negative return values are passed through, negative return values are thrown as
62      * exceptions.</p>
63      *
64      * @param errorFlag error to throw as an exception.
65      * @throws {@link BufferQueueAbandonedException} for BAD_VALUE.
66      * @throws {@link UnsupportedOperationException} for an unknown negative error code.
67      * @return {@code errorFlag} if the value was non-negative, throws otherwise.
68      */
throwOnError(int errorFlag)69     public static int throwOnError(int errorFlag) throws BufferQueueAbandonedException {
70         if (errorFlag == NO_ERROR) {
71             return NO_ERROR;
72         } else if (errorFlag == BAD_VALUE) {
73             throw new BufferQueueAbandonedException();
74         }
75 
76         if (errorFlag < 0) {
77             throw new UnsupportedOperationException("Unknown error " + errorFlag);
78         }
79         return errorFlag;
80     }
81 
82     /**
83      * Throw error codes returned by the camera service as exceptions.
84      *
85      * @param errorFlag error to throw as an exception.
86      */
throwOnServiceError(int errorFlag)87     public static void throwOnServiceError(int errorFlag) {
88         int errorCode = ICameraService.ERROR_INVALID_OPERATION;
89         String errorMsg;
90 
91         if (errorFlag >= NO_ERROR) {
92             return;
93         } else if (errorFlag == PERMISSION_DENIED) {
94             errorCode = ICameraService.ERROR_PERMISSION_DENIED;
95             errorMsg = "Lacking privileges to access camera service";
96         } else if (errorFlag == ALREADY_EXISTS) {
97             // This should be handled at the call site. Typically this isn't bad,
98             // just means we tried to do an operation that already completed.
99             return;
100         } else if (errorFlag == BAD_VALUE) {
101             errorCode = ICameraService.ERROR_ILLEGAL_ARGUMENT;
102             errorMsg = "Bad argument passed to camera service";
103         } else if (errorFlag == DEAD_OBJECT) {
104             errorCode = ICameraService.ERROR_DISCONNECTED;
105             errorMsg = "Camera service not available";
106         } else if (errorFlag == TIMED_OUT) {
107             errorCode = ICameraService.ERROR_INVALID_OPERATION;
108             errorMsg = "Operation timed out in camera service";
109         } else if (errorFlag == -EACCES) {
110             errorCode = ICameraService.ERROR_DISABLED;
111             errorMsg = "Camera disabled by policy";
112         } else if (errorFlag == -EBUSY) {
113             errorCode = ICameraService.ERROR_CAMERA_IN_USE;
114             errorMsg = "Camera already in use";
115         } else if (errorFlag == -EUSERS) {
116             errorCode = ICameraService.ERROR_MAX_CAMERAS_IN_USE;
117             errorMsg = "Maximum number of cameras in use";
118         } else if (errorFlag == -ENODEV) {
119             errorCode = ICameraService.ERROR_DISCONNECTED;
120             errorMsg = "Camera device not available";
121         } else if (errorFlag == -EOPNOTSUPP) {
122             errorCode = ICameraService.ERROR_DEPRECATED_HAL;
123             errorMsg = "Deprecated camera HAL does not support this";
124         } else if (errorFlag == INVALID_OPERATION) {
125             errorCode = ICameraService.ERROR_INVALID_OPERATION;
126             errorMsg = "Illegal state encountered in camera service.";
127         } else {
128             errorCode = ICameraService.ERROR_INVALID_OPERATION;
129             errorMsg = "Unknown camera device error " + errorFlag;
130         }
131 
132         throw new ServiceSpecificException(errorCode, errorMsg);
133     }
134 
LegacyExceptionUtils()135     private LegacyExceptionUtils() {
136         throw new AssertionError();
137     }
138 }
139