Replace hard-coded errno values with OsConstants

Errno values have been hard-coded inside java code. On the native side
however, bionic's errno.h is used (through utils/Errors.h). Some of
the numbers are architecture dependent (EOPNOTSUPP, ETIMEDOUT...).

This causes Camera app to crash on MIPS devices. There is a check for
expected errors, in CameraBinderDecorator.throwOnError, but the error
(EOPNOTSUPP) is not recognized and an exception is thrown.

Change-Id: I8bcac8f1ced50c76614f566a6e624967a18a25e1
This commit is contained in:
Lazar Trsic
2015-07-07 17:31:20 +02:00
parent 3fe5a65b1c
commit 8ea56f6851
8 changed files with 110 additions and 112 deletions

View File

@@ -47,6 +47,8 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import static android.system.OsConstants.*;
/**
* The Camera class is used to set image capture settings, start/stop preview,
* snap pictures, and retrieve frames for encoding for video. This class is a
@@ -173,13 +175,6 @@ public class Camera {
private final Object mAutoFocusCallbackLock = new Object();
private static final int NO_ERROR = 0;
private static final int EACCESS = -13;
private static final int ENODEV = -19;
private static final int EBUSY = -16;
private static final int EINVAL = -22;
private static final int ENOSYS = -38;
private static final int EUSERS = -87;
private static final int EOPNOTSUPP = -95;
/**
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -415,30 +410,28 @@ public class Camera {
private Camera(int cameraId, int halVersion) {
int err = cameraInitVersion(cameraId, halVersion);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
throw new RuntimeException("Fail to connect to camera service");
case ENODEV:
throw new RuntimeException("Camera initialization failed");
case ENOSYS:
throw new RuntimeException("Camera initialization failed because some methods"
+ " are not implemented");
case EOPNOTSUPP:
throw new RuntimeException("Camera initialization failed because the hal"
+ " version is not supported by this device");
case EINVAL:
throw new RuntimeException("Camera initialization failed because the input"
+ " arugments are invalid");
case EBUSY:
throw new RuntimeException("Camera initialization failed because the camera"
+ " device was already opened");
case EUSERS:
throw new RuntimeException("Camera initialization failed because the max"
+ " number of camera devices were already opened");
default:
// Should never hit this.
throw new RuntimeException("Unknown camera error");
if (err == -EACCES) {
throw new RuntimeException("Fail to connect to camera service");
} else if (err == -ENODEV) {
throw new RuntimeException("Camera initialization failed");
} else if (err == -ENOSYS) {
throw new RuntimeException("Camera initialization failed because some methods"
+ " are not implemented");
} else if (err == -EOPNOTSUPP) {
throw new RuntimeException("Camera initialization failed because the hal"
+ " version is not supported by this device");
} else if (err == -EINVAL) {
throw new RuntimeException("Camera initialization failed because the input"
+ " arugments are invalid");
} else if (err == -EBUSY) {
throw new RuntimeException("Camera initialization failed because the camera"
+ " device was already opened");
} else if (err == -EUSERS) {
throw new RuntimeException("Camera initialization failed because the max"
+ " number of camera devices were already opened");
}
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}
@@ -490,15 +483,13 @@ public class Camera {
Camera(int cameraId) {
int err = cameraInitNormal(cameraId);
if (checkInitErrors(err)) {
switch(err) {
case EACCESS:
throw new RuntimeException("Fail to connect to camera service");
case ENODEV:
throw new RuntimeException("Camera initialization failed");
default:
// Should never hit this.
throw new RuntimeException("Unknown camera error");
if (err == -EACCES) {
throw new RuntimeException("Fail to connect to camera service");
} else if (err == -ENODEV) {
throw new RuntimeException("Camera initialization failed");
}
// Should never hit this.
throw new RuntimeException("Unknown camera error");
}
}

View File

@@ -43,6 +43,9 @@ import android.view.Surface;
import java.util.ArrayList;
import java.util.List;
import static android.system.OsConstants.EACCES;
import static android.system.OsConstants.ENODEV;
/**
* Compatibility implementation of the Camera2 API binder interface.
*
@@ -88,6 +91,14 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
mSurfaceIdCounter = 0;
}
private static int translateErrorsFromCamera1(int errorCode) {
if (errorCode == -EACCES) {
return CameraBinderDecorator.PERMISSION_DENIED;
}
return errorCode;
}
/**
* Create a separate looper/thread for the camera to run on; open the camera.
*
@@ -382,7 +393,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot submit request, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -402,7 +413,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot submit request list, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -421,7 +432,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot cancel request, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -442,7 +453,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot begin configure, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -462,7 +473,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot end configure, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
ArrayList<Surface> surfaces = null;
@@ -490,7 +501,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot delete stream, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -515,7 +526,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot create stream, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -552,7 +563,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot create default request, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
CameraMetadataNative template;
@@ -585,7 +596,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot wait until idle, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -605,7 +616,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot flush, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
synchronized(mConfigureLock) {
@@ -627,7 +638,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot prepare stream, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
// LEGACY doesn't support actual prepare, just signal success right away
@@ -647,7 +658,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
if (mLegacyDevice.isClosed()) {
Log.e(TAG, "Cannot tear down stream, device has been closed.");
return CameraBinderDecorator.ENODEV;
return -ENODEV;
}
// LEGACY doesn't support actual teardown, so just a no-op

View File

@@ -19,6 +19,8 @@ package android.hardware.camera2.legacy;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.util.AndroidException;
import static android.system.OsConstants.ENODEV;
/**
* Utility class containing exception handling used solely by the compatibility mode shim.
*/
@@ -51,18 +53,15 @@ public class LegacyExceptionUtils {
* exceptions.</p>
*
* @param errorFlag error to throw as an exception.
* @throws {@link BufferQueueAbandonedException} for {@link CameraBinderDecorator#ENODEV}.
* @throws {@link BufferQueueAbandonedException} for -ENODEV.
* @throws {@link UnsupportedOperationException} for an unknown negative error code.
* @return {@code errorFlag} if the value was non-negative, throws otherwise.
*/
public static int throwOnError(int errorFlag) throws BufferQueueAbandonedException {
switch (errorFlag) {
case CameraBinderDecorator.NO_ERROR: {
return CameraBinderDecorator.NO_ERROR;
}
case CameraBinderDecorator.BAD_VALUE: {
throw new BufferQueueAbandonedException();
}
if (errorFlag == CameraBinderDecorator.NO_ERROR) {
return CameraBinderDecorator.NO_ERROR;
} else if (errorFlag == -ENODEV) {
throw new BufferQueueAbandonedException();
}
if (errorFlag < 0) {

View File

@@ -22,6 +22,7 @@ import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
import static android.system.OsConstants.*;
import android.os.DeadObjectException;
import android.os.RemoteException;
@@ -37,12 +38,12 @@ import java.lang.reflect.Method;
public class CameraBinderDecorator {
public static final int NO_ERROR = 0;
public static final int PERMISSION_DENIED = -1;
public static final int ALREADY_EXISTS = -17;
public static final int BAD_VALUE = -22;
public static final int DEAD_OBJECT = -32;
public static final int INVALID_OPERATION = -38;
public static final int TIMED_OUT = -110;
public static final int PERMISSION_DENIED = -EPERM;
public static final int ALREADY_EXISTS = -EEXIST;
public static final int BAD_VALUE = -EINVAL;
public static final int DEAD_OBJECT = -ENOSYS;
public static final int INVALID_OPERATION = -EPIPE;
public static final int TIMED_OUT = -ETIMEDOUT;
/**
* TODO: add as error codes in Errors.h
@@ -52,12 +53,6 @@ public class CameraBinderDecorator {
* - NOT_SUPPORTED
* - TOO_MANY_USERS
*/
public static final int EACCES = -13;
public static final int EBUSY = -16;
public static final int ENODEV = -19;
public static final int EOPNOTSUPP = -95;
public static final int EUSERS = -87;
static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
@@ -101,35 +96,34 @@ public class CameraBinderDecorator {
* @param errorFlag error to throw as an exception.
*/
public static void throwOnError(int errorFlag) {
switch (errorFlag) {
case NO_ERROR:
return;
case PERMISSION_DENIED:
throw new SecurityException("Lacking privileges to access camera service");
case ALREADY_EXISTS:
// This should be handled at the call site. Typically this isn't bad,
// just means we tried to do an operation that already completed.
return;
case BAD_VALUE:
throw new IllegalArgumentException("Bad argument passed to camera service");
case DEAD_OBJECT:
throw new CameraRuntimeException(CAMERA_DISCONNECTED);
case TIMED_OUT:
throw new CameraRuntimeException(CAMERA_ERROR,
"Operation timed out in camera service");
case EACCES:
throw new CameraRuntimeException(CAMERA_DISABLED);
case EBUSY:
throw new CameraRuntimeException(CAMERA_IN_USE);
case EUSERS:
throw new CameraRuntimeException(MAX_CAMERAS_IN_USE);
case ENODEV:
throw new CameraRuntimeException(CAMERA_DISCONNECTED);
case EOPNOTSUPP:
throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL);
case INVALID_OPERATION:
throw new CameraRuntimeException(CAMERA_ERROR,
"Illegal state encountered in camera service.");
if (errorFlag == NO_ERROR) {
return;
} else if (errorFlag == PERMISSION_DENIED) {
throw new SecurityException("Lacking privileges to access camera service");
} else if (errorFlag == ALREADY_EXISTS) {
// This should be handled at the call site. Typically this isn't bad,
// just means we tried to do an operation that already completed.
return;
} else if (errorFlag == BAD_VALUE) {
throw new IllegalArgumentException("Bad argument passed to camera service");
} else if (errorFlag == DEAD_OBJECT) {
throw new CameraRuntimeException(CAMERA_DISCONNECTED);
} else if (errorFlag == TIMED_OUT) {
throw new CameraRuntimeException(CAMERA_ERROR,
"Operation timed out in camera service");
} else if (errorFlag == -EACCES) {
throw new CameraRuntimeException(CAMERA_DISABLED);
} else if (errorFlag == -EBUSY) {
throw new CameraRuntimeException(CAMERA_IN_USE);
} else if (errorFlag == -EUSERS) {
throw new CameraRuntimeException(MAX_CAMERAS_IN_USE);
} else if (errorFlag == -ENODEV) {
throw new CameraRuntimeException(CAMERA_DISCONNECTED);
} else if (errorFlag == -EOPNOTSUPP) {
throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL);
} else if (errorFlag == INVALID_OPERATION) {
throw new CameraRuntimeException(CAMERA_ERROR,
"Illegal state encountered in camera service.");
}
/**

View File

@@ -25,6 +25,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
import static android.system.OsConstants.*;
/**
* The SoundTrigger class provides access via JNI to the native service managing
* the sound trigger HAL.
@@ -35,11 +37,11 @@ public class SoundTrigger {
public static final int STATUS_OK = 0;
public static final int STATUS_ERROR = Integer.MIN_VALUE;
public static final int STATUS_PERMISSION_DENIED = -1;
public static final int STATUS_NO_INIT = -19;
public static final int STATUS_BAD_VALUE = -22;
public static final int STATUS_DEAD_OBJECT = -32;
public static final int STATUS_INVALID_OPERATION = -38;
public static final int STATUS_PERMISSION_DENIED = -EPERM;
public static final int STATUS_NO_INIT = -ENODEV;
public static final int STATUS_BAD_VALUE = -EINVAL;
public static final int STATUS_DEAD_OBJECT = -EPIPE;
public static final int STATUS_INVALID_OPERATION = -ENOSYS;
/*****************************************************************************
* A ModuleProperties describes a given sound trigger hardware module

View File

@@ -129,7 +129,7 @@ public class CameraBinderTest extends AndroidTestCase {
int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
if (res != CameraBinderTestUtils.NO_ERROR && res != CameraBinderTestUtils.EOPNOTSUPP) {
if (res != CameraBinderTestUtils.NO_ERROR && res != -android.system.OsConstants.EOPNOTSUPP) {
fail("Camera service returned bad value when queried if it supports camera2 api: "
+ res + " for camera ID " + cameraId);
}

View File

@@ -2,6 +2,7 @@
package com.android.mediaframeworktest.integration;
import static org.junit.Assert.assertNotNull;
import static android.system.OsConstants.*;
import android.content.Context;
import android.content.pm.FeatureInfo;
@@ -18,11 +19,10 @@ public class CameraBinderTestUtils {
static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
protected static final int USE_CALLING_UID = -1;
protected static final int BAD_VALUE = -22;
protected static final int INVALID_OPERATION = -38;
protected static final int ALREADY_EXISTS = -17;
protected static final int BAD_VALUE = -EINVAL;
protected static final int INVALID_OPERATION = -ENOSYS;
protected static final int ALREADY_EXISTS = -EEXIST;
public static final int NO_ERROR = 0;
public static final int EOPNOTSUPP = -95;
private final Context mContext;
public CameraBinderTestUtils(Context context) {

View File

@@ -27,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import static org.mockito.Mockito.*;
import static android.hardware.camera2.utils.CameraBinderDecorator.*;
import static android.hardware.camera2.CameraAccessException.*;
import static android.system.OsConstants.*;
import junit.framework.Assert;
@@ -78,9 +79,9 @@ public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase {
when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS);
when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE);
when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT);
when(mock.doSomethingBadPolicy()).thenReturn(EACCES);
when(mock.doSomethingDeviceBusy()).thenReturn(EBUSY);
when(mock.doSomethingNoSuchDevice()).thenReturn(ENODEV);
when(mock.doSomethingBadPolicy()).thenReturn(-EACCES);
when(mock.doSomethingDeviceBusy()).thenReturn(-EBUSY);
when(mock.doSomethingNoSuchDevice()).thenReturn(-ENODEV);
when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT);
when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException());
when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow(