1e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin/* 2e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Copyright (C) 2013 The Android Open Source Project 3e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 4e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Licensed under the Apache License, Version 2.0 (the "License"); 5e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * you may not use this file except in compliance with the License. 6e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * You may obtain a copy of the License at 7e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 8e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * http://www.apache.org/licenses/LICENSE-2.0 9e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 10e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Unless required by applicable law or agreed to in writing, software 11e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * distributed under the License is distributed on an "AS IS" BASIS, 12e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * See the License for the specific language governing permissions and 14e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * limitations under the License. 15e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 16e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 172f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalapackage android.hardware.camera2.utils; 18e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 192f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaimport static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED; 202f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaimport static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED; 212f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvalaimport static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE; 229503785393ba8999473b7a924ede2baf520e367cEino-Ville Talvalaimport static android.hardware.camera2.CameraAccessException.CAMERA_ERROR; 2368ebc1a7b4c18d587612891250f17f36edfe1bc1Zhijun Heimport static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE; 2466ef64514464a1bb9c7931993cc8db3d7539f39aRuben Brunkimport static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL; 25e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 26e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.DeadObjectException; 27e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.RemoteException; 28e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 29e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport java.lang.reflect.Method; 30e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 31e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin/** 32bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala * Translate camera device status_t return values into exceptions. 33e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 342f1a2e423e0fbb64467d6fcfa4e82c6384f31210Eino-Ville Talvala * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance 35e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @hide 36e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 37e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinpublic class CameraBinderDecorator { 38e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 39e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int NO_ERROR = 0; 40e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int PERMISSION_DENIED = -1; 41e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int ALREADY_EXISTS = -17; 42e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int BAD_VALUE = -22; 43e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int DEAD_OBJECT = -32; 44feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk public static final int INVALID_OPERATION = -38; 459503785393ba8999473b7a924ede2baf520e367cEino-Ville Talvala public static final int TIMED_OUT = -110; 46e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 47e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 48e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * TODO: add as error codes in Errors.h 49e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * - POLICY_PROHIBITS 50e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * - RESOURCE_BUSY 51e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * - NO_SUCH_DEVICE 524961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * - NOT_SUPPORTED 534961bc88d7bab869a5296789d26fcfa31ad5f644Igor Murashkin * - TOO_MANY_USERS 54e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 55e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int EACCES = -13; 56e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int EBUSY = -16; 57e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int ENODEV = -19; 586462be7fa0234ca1a285f4f40089f9be1fed8316Ruben Brunk public static final int EOPNOTSUPP = -95; 599bd5f1e6dff31e2299c065157ba3a43bc79a9d48Zhijun He public static final int EUSERS = -87; 60e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk 62bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala static class CameraBinderDecoratorListener implements Decorator.DecoratorListener { 63e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 64e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 65e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onBeforeInvocation(Method m, Object[] args) { 66e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 67e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 68e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 69e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onAfterInvocation(Method m, Object[] args, Object result) { 70e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // int return type => status_t => convert to exception 71e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (m.getReturnType() == Integer.TYPE) { 72e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin int returnValue = (Integer) result; 7385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk throwOnError(returnValue); 74e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 75e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 76e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 77e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 78e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public boolean onCatchException(Method m, Object[] args, Throwable t) { 79e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 80e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (t instanceof DeadObjectException) { 81bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(CAMERA_DISCONNECTED, 82e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin "Process hosting the camera service has died unexpectedly", 83bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala t); 84e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } else if (t instanceof RemoteException) { 85e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new UnsupportedOperationException("An unknown RemoteException was thrown" + 86e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin " which should never happen.", t); 87e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 88e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 89e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return false; 90e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 91e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 92e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 93e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onFinally(Method m, Object[] args) { 94e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 95e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 96e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 97e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 98e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 9985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk * Throw error codes returned by the camera service as exceptions. 10085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk * 10185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk * @param errorFlag error to throw as an exception. 10285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk */ 10385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk public static void throwOnError(int errorFlag) { 10485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk switch (errorFlag) { 10585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case NO_ERROR: 10685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk return; 10785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case PERMISSION_DENIED: 10885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk throw new SecurityException("Lacking privileges to access camera service"); 10985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case ALREADY_EXISTS: 11085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk // This should be handled at the call site. Typically this isn't bad, 11185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk // just means we tried to do an operation that already completed. 11285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk return; 11385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case BAD_VALUE: 11485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk throw new IllegalArgumentException("Bad argument passed to camera service"); 11585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case DEAD_OBJECT: 116bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(CAMERA_DISCONNECTED); 1179503785393ba8999473b7a924ede2baf520e367cEino-Ville Talvala case TIMED_OUT: 1189503785393ba8999473b7a924ede2baf520e367cEino-Ville Talvala throw new CameraRuntimeException(CAMERA_ERROR, 1199503785393ba8999473b7a924ede2baf520e367cEino-Ville Talvala "Operation timed out in camera service"); 12085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case EACCES: 121bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(CAMERA_DISABLED); 12285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case EBUSY: 123bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(CAMERA_IN_USE); 12485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case EUSERS: 125bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(MAX_CAMERAS_IN_USE); 12685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case ENODEV: 127bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(CAMERA_DISCONNECTED); 12885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk case EOPNOTSUPP: 129bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL); 130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk case INVALID_OPERATION: 1319503785393ba8999473b7a924ede2baf520e367cEino-Ville Talvala throw new CameraRuntimeException(CAMERA_ERROR, 132bd9b106806f9792be210cc2d9848d8b1f4b9664dEino-Ville Talvala "Illegal state encountered in camera service."); 13385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk } 13485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk 13585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk /** 13685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk * Trap the rest of the negative return values. If we have known 13785c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk * error codes i.e. ALREADY_EXISTS that aren't really runtime 13885c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk * errors, then add them to the top switch statement 13985c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk */ 14085c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk if (errorFlag < 0) { 14185c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk throw new UnsupportedOperationException(String.format("Unknown error %d", 14285c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk errorFlag)); 14385c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk } 14485c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk } 14585c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk 14685c4388de1fea3d45783f07895c2b113c4cc1ba5Ruben Brunk /** 147e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * <p> 148e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Wraps the type T with a proxy that will check 'status_t' return codes 149e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * from the native side of the camera service, and throw Java exceptions 150e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * automatically based on the code. 151e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * </p> 152e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * <p> 153e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * In addition it also rewrites binder's RemoteException into either a 154e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * CameraAccessException or an UnsupportedOperationException. 155e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * </p> 156e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * <p> 157e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * As a result of calling any method on the proxy, RemoteException is 158e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * guaranteed never to be thrown. 159e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * </p> 160e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 161e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @param obj object that will serve as the target for all method calls 162e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @param <T> the type of the element you want to wrap. This must be an interface. 163e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @return a proxy that will intercept all invocations to obj 164e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 165e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static <T> T newInstance(T obj) { 166e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener()); 167e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 168e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin} 169