blob: e535e002ef9cf9f4fb88457c35f418767d3dcea7 [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;
67
68 switch (returnValue) {
69 case NO_ERROR:
70 return;
71 case PERMISSION_DENIED:
72 throw new SecurityException("Lacking privileges to access camera service");
73 case ALREADY_EXISTS:
Igor Murashkin70725502013-06-25 20:27:06 +000074 // This should be handled at the call site. Typically this isn't bad,
75 // just means we tried to do an operation that already completed.
Igor Murashkine363fbb2013-06-25 20:26:06 +000076 return;
77 case BAD_VALUE:
78 throw new IllegalArgumentException("Bad argument passed to camera service");
79 case DEAD_OBJECT:
80 UncheckedThrow.throwAnyException(new CameraRuntimeException(
81 CAMERA_DISCONNECTED));
Igor Murashkine363fbb2013-06-25 20:26:06 +000082 case EACCES:
83 UncheckedThrow.throwAnyException(new CameraRuntimeException(
84 CAMERA_DISABLED));
85 case EBUSY:
86 UncheckedThrow.throwAnyException(new CameraRuntimeException(
87 CAMERA_IN_USE));
Zhijun He9bd5f1e2013-09-23 13:07:57 -070088 case EUSERS:
Zhijun He68ebc1a2013-09-15 11:55:44 -070089 UncheckedThrow.throwAnyException(new CameraRuntimeException(
90 MAX_CAMERAS_IN_USE));
Igor Murashkine363fbb2013-06-25 20:26:06 +000091 case ENODEV:
92 UncheckedThrow.throwAnyException(new CameraRuntimeException(
93 CAMERA_DISCONNECTED));
Ruben Brunk6462be72013-09-04 12:09:23 -070094 case EOPNOTSUPP:
Ruben Brunk66ef6452013-08-08 13:05:30 -070095 UncheckedThrow.throwAnyException(new CameraRuntimeException(
96 CAMERA_DEPRECATED_HAL));
Igor Murashkine363fbb2013-06-25 20:26:06 +000097 }
98
99 /**
100 * Trap the rest of the negative return values. If we have known
101 * error codes i.e. ALREADY_EXISTS that aren't really runtime
102 * errors, then add them to the top switch statement
103 */
104 if (returnValue < 0) {
105 throw new UnsupportedOperationException(String.format("Unknown error %d",
106 returnValue));
107 }
108 }
109 }
110
111 @Override
112 public boolean onCatchException(Method m, Object[] args, Throwable t) {
113
114 if (t instanceof DeadObjectException) {
115 UncheckedThrow.throwAnyException(new CameraRuntimeException(
116 CAMERA_DISCONNECTED,
117 "Process hosting the camera service has died unexpectedly",
118 t));
119 } else if (t instanceof RemoteException) {
120 throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
121 " which should never happen.", t);
122 }
123
124 return false;
125 }
126
127 @Override
128 public void onFinally(Method m, Object[] args) {
129 }
130
131 }
132
133 /**
134 * <p>
135 * Wraps the type T with a proxy that will check 'status_t' return codes
136 * from the native side of the camera service, and throw Java exceptions
137 * automatically based on the code.
138 * </p>
139 * <p>
140 * In addition it also rewrites binder's RemoteException into either a
141 * CameraAccessException or an UnsupportedOperationException.
142 * </p>
143 * <p>
144 * As a result of calling any method on the proxy, RemoteException is
145 * guaranteed never to be thrown.
146 * </p>
147 *
148 * @param obj object that will serve as the target for all method calls
149 * @param <T> the type of the element you want to wrap. This must be an interface.
150 * @return a proxy that will intercept all invocations to obj
151 */
152 public static <T> T newInstance(T obj) {
153 return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
154 }
155}