blob: 328ccbe4cb981066a0b4d597320899f83901f1e6 [file] [log] [blame]
Igor Murashkine363fbb2013-06-25 20:26:06 +00001/*
2 * Copyright (C) 2013 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
Eino-Ville Talvala2f1a2e42013-07-25 17:12:05 -070017package android.hardware.camera2.utils;
Igor Murashkine363fbb2013-06-25 20:26:06 +000018
Eino-Ville Talvala2f1a2e42013-07-25 17:12:05 -070019import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
20import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
21import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
Zhijun He68ebc1a2013-09-15 11:55:44 -070022import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
Ruben Brunk66ef6452013-08-08 13:05:30 -070023import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
Igor Murashkine363fbb2013-06-25 20:26:06 +000024
25import android.os.DeadObjectException;
26import android.os.RemoteException;
27
28import java.lang.reflect.Method;
29
30/**
31 * Translate camera service status_t return values into exceptions.
32 *
Eino-Ville Talvala2f1a2e42013-07-25 17:12:05 -070033 * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
Igor Murashkine363fbb2013-06-25 20:26:06 +000034 * @hide
35 */
36public class CameraBinderDecorator {
37
38 public static final int NO_ERROR = 0;
39 public static final int PERMISSION_DENIED = -1;
40 public static final int ALREADY_EXISTS = -17;
41 public static final int BAD_VALUE = -22;
42 public static final int DEAD_OBJECT = -32;
43
44 /**
45 * TODO: add as error codes in Errors.h
46 * - POLICY_PROHIBITS
47 * - RESOURCE_BUSY
48 * - NO_SUCH_DEVICE
49 */
50 public static final int EACCES = -13;
51 public static final int EBUSY = -16;
52 public static final int ENODEV = -19;
Ruben Brunk6462be72013-09-04 12:09:23 -070053 public static final int EOPNOTSUPP = -95;
Zhijun He9bd5f1e2013-09-23 13:07:57 -070054 public static final int EUSERS = -87;
Igor Murashkine363fbb2013-06-25 20:26:06 +000055
56 private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
57
58 @Override
59 public void onBeforeInvocation(Method m, Object[] args) {
60 }
61
62 @Override
63 public void onAfterInvocation(Method m, Object[] args, Object result) {
64 // int return type => status_t => convert to exception
65 if (m.getReturnType() == Integer.TYPE) {
66 int returnValue = (Integer) result;
Ruben Brunk85c43882014-02-21 17:40:51 -080067 throwOnError(returnValue);
Igor Murashkine363fbb2013-06-25 20:26:06 +000068 }
69 }
70
71 @Override
72 public boolean onCatchException(Method m, Object[] args, Throwable t) {
73
74 if (t instanceof DeadObjectException) {
75 UncheckedThrow.throwAnyException(new CameraRuntimeException(
76 CAMERA_DISCONNECTED,
77 "Process hosting the camera service has died unexpectedly",
78 t));
79 } else if (t instanceof RemoteException) {
80 throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
81 " which should never happen.", t);
82 }
83
84 return false;
85 }
86
87 @Override
88 public void onFinally(Method m, Object[] args) {
89 }
90
91 }
92
93 /**
Ruben Brunk85c43882014-02-21 17:40:51 -080094 * Throw error codes returned by the camera service as exceptions.
95 *
96 * @param errorFlag error to throw as an exception.
97 */
98 public static void throwOnError(int errorFlag) {
99 switch (errorFlag) {
100 case NO_ERROR:
101 return;
102 case PERMISSION_DENIED:
103 throw new SecurityException("Lacking privileges to access camera service");
104 case ALREADY_EXISTS:
105 // This should be handled at the call site. Typically this isn't bad,
106 // just means we tried to do an operation that already completed.
107 return;
108 case BAD_VALUE:
109 throw new IllegalArgumentException("Bad argument passed to camera service");
110 case DEAD_OBJECT:
111 UncheckedThrow.throwAnyException(new CameraRuntimeException(
112 CAMERA_DISCONNECTED));
113 case EACCES:
114 UncheckedThrow.throwAnyException(new CameraRuntimeException(
115 CAMERA_DISABLED));
116 case EBUSY:
117 UncheckedThrow.throwAnyException(new CameraRuntimeException(
118 CAMERA_IN_USE));
119 case EUSERS:
120 UncheckedThrow.throwAnyException(new CameraRuntimeException(
121 MAX_CAMERAS_IN_USE));
122 case ENODEV:
123 UncheckedThrow.throwAnyException(new CameraRuntimeException(
124 CAMERA_DISCONNECTED));
125 case EOPNOTSUPP:
126 UncheckedThrow.throwAnyException(new CameraRuntimeException(
127 CAMERA_DEPRECATED_HAL));
128 }
129
130 /**
131 * Trap the rest of the negative return values. If we have known
132 * error codes i.e. ALREADY_EXISTS that aren't really runtime
133 * errors, then add them to the top switch statement
134 */
135 if (errorFlag < 0) {
136 throw new UnsupportedOperationException(String.format("Unknown error %d",
137 errorFlag));
138 }
139 }
140
141 /**
Igor Murashkine363fbb2013-06-25 20:26:06 +0000142 * <p>
143 * Wraps the type T with a proxy that will check 'status_t' return codes
144 * from the native side of the camera service, and throw Java exceptions
145 * automatically based on the code.
146 * </p>
147 * <p>
148 * In addition it also rewrites binder's RemoteException into either a
149 * CameraAccessException or an UnsupportedOperationException.
150 * </p>
151 * <p>
152 * As a result of calling any method on the proxy, RemoteException is
153 * guaranteed never to be thrown.
154 * </p>
155 *
156 * @param obj object that will serve as the target for all method calls
157 * @param <T> the type of the element you want to wrap. This must be an interface.
158 * @return a proxy that will intercept all invocations to obj
159 */
160 public static <T> T newInstance(T obj) {
161 return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
162 }
163}