CameraBinderDecorator.java revision e363fbb2647aeb5ef4c87160d84c6b9ae8d45598
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 17e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinpackage android.hardware.photography.utils; 18e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 19e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport static android.hardware.photography.CameraAccessException.CAMERA_DISABLED; 20e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport static android.hardware.photography.CameraAccessException.CAMERA_DISCONNECTED; 21e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport static android.hardware.photography.CameraAccessException.CAMERA_IN_USE; 22e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 23e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.DeadObjectException; 24e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport android.os.RemoteException; 25e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 26e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinimport java.lang.reflect.Method; 27e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 28e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin/** 29e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Translate camera service status_t return values into exceptions. 30e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 31e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @see android.hardware.photography.utils.CameraBinderDecorator#newInstance 32e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @hide 33e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 34e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkinpublic class CameraBinderDecorator { 35e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 36e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int NO_ERROR = 0; 37e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int PERMISSION_DENIED = -1; 38e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int ALREADY_EXISTS = -17; 39e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int BAD_VALUE = -22; 40e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int DEAD_OBJECT = -32; 41e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 42e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 43e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * TODO: add as error codes in Errors.h 44e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * - POLICY_PROHIBITS 45e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * - RESOURCE_BUSY 46e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * - NO_SUCH_DEVICE 47e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 48e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int EACCES = -13; 49e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int EBUSY = -16; 50e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static final int ENODEV = -19; 51e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 52e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener { 53e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 54e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 55e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onBeforeInvocation(Method m, Object[] args) { 56e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 57e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 58e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 59e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onAfterInvocation(Method m, Object[] args, Object result) { 60e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // int return type => status_t => convert to exception 61e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (m.getReturnType() == Integer.TYPE) { 62e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin int returnValue = (Integer) result; 63e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 64e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin switch (returnValue) { 65e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case NO_ERROR: 66e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return; 67e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case PERMISSION_DENIED: 68e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new SecurityException("Lacking privileges to access camera service"); 69e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case ALREADY_EXISTS: 70e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return; 71e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case BAD_VALUE: 72e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new IllegalArgumentException("Bad argument passed to camera service"); 73e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case DEAD_OBJECT: 74e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin UncheckedThrow.throwAnyException(new CameraRuntimeException( 75e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin CAMERA_DISCONNECTED)); 76e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // TODO: Camera service (native side) should return 77e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // EACCES error 78e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin // when there's a policy manager disabled causing this 79e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case EACCES: 80e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin UncheckedThrow.throwAnyException(new CameraRuntimeException( 81e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin CAMERA_DISABLED)); 82e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case EBUSY: 83e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin UncheckedThrow.throwAnyException(new CameraRuntimeException( 84e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin CAMERA_IN_USE)); 85e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin case ENODEV: 86e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin UncheckedThrow.throwAnyException(new CameraRuntimeException( 87e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin CAMERA_DISCONNECTED)); 88e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 89e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 90e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 91e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Trap the rest of the negative return values. If we have known 92e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * error codes i.e. ALREADY_EXISTS that aren't really runtime 93e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * errors, then add them to the top switch statement 94e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 95e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (returnValue < 0) { 96e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new UnsupportedOperationException(String.format("Unknown error %d", 97e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin returnValue)); 98e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 99e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 100e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 101e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 102e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 103e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public boolean onCatchException(Method m, Object[] args, Throwable t) { 104e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 105e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin if (t instanceof DeadObjectException) { 106e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin UncheckedThrow.throwAnyException(new CameraRuntimeException( 107e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin CAMERA_DISCONNECTED, 108e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin "Process hosting the camera service has died unexpectedly", 109e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin t)); 110e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } else if (t instanceof RemoteException) { 111e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin throw new UnsupportedOperationException("An unknown RemoteException was thrown" + 112e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin " which should never happen.", t); 113e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 114e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 115e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return false; 116e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 117e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 118e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin @Override 119e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public void onFinally(Method m, Object[] args) { 120e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 121e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 122e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 123e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin 124e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin /** 125e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * <p> 126e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * Wraps the type T with a proxy that will check 'status_t' return codes 127e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * from the native side of the camera service, and throw Java exceptions 128e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * automatically based on the code. 129e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * </p> 130e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * <p> 131e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * In addition it also rewrites binder's RemoteException into either a 132e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * CameraAccessException or an UnsupportedOperationException. 133e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * </p> 134e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * <p> 135e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * As a result of calling any method on the proxy, RemoteException is 136e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * guaranteed never to be thrown. 137e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * </p> 138e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * 139e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @param obj object that will serve as the target for all method calls 140e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @param <T> the type of the element you want to wrap. This must be an interface. 141e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin * @return a proxy that will intercept all invocations to obj 142e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin */ 143e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin public static <T> T newInstance(T obj) { 144e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener()); 145e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin } 146e363fbb2647aeb5ef4c87160d84c6b9ae8d45598Igor Murashkin} 147