Merge "camera3: Pass vendor tags through binder."

This commit is contained in:
Ruben Brunk
2014-03-13 20:18:36 +00:00
committed by Android (Google) Code Review
5 changed files with 118 additions and 41 deletions

View File

@@ -61,4 +61,12 @@ interface ICameraService
int removeListener(ICameraServiceListener listener);
int getCameraCharacteristics(int cameraId, out CameraMetadataNative info);
/**
* The java stubs for this method are not intended to be used. Please use
* the native stub in frameworks/av/include/camera/ICameraService.h instead.
* The BinderHolder output is being used as a placeholder, and will not be
* well-formatted in the generated java method.
*/
int getCameraVendorTagDescriptor(out BinderHolder desc);
}

View File

@@ -48,6 +48,8 @@ import java.util.ArrayList;
*/
public final class CameraManager {
private static final String TAG = "CameraManager";
/**
* This should match the ICameraService definition
*/
@@ -78,6 +80,19 @@ public final class CameraManager {
*/
mCameraService = CameraBinderDecorator.newInstance(cameraServiceRaw);
try {
int err = CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor();
if (err == CameraBinderDecorator.EOPNOTSUPP) {
Log.w(TAG, "HAL version doesn't vendor tags.");
} else {
CameraBinderDecorator.throwOnError(CameraMetadataNative.
nativeSetupGlobalVendorTagDescriptor());
}
} catch(CameraRuntimeException e) {
throw new IllegalStateException("Failed to setup camera vendor tags",
e.asChecked());
}
try {
mCameraService.addListener(new CameraServiceListener());
} catch(CameraRuntimeException e) {

View File

@@ -104,6 +104,18 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable {
nativeReadFromParcel(in);
}
/**
* Set the global client-side vendor tag descriptor to allow use of vendor
* tags in camera applications.
*
* @return int A native status_t value corresponding to one of the
* {@link CameraBinderDecorator} integer constants.
* @see CameraBinderDecorator#throwOnError
*
* @hide
*/
public static native int nativeSetupGlobalVendorTagDescriptor();
/**
* Set a camera metadata field to a value. The field definitions can be
* found in {@link CameraCharacteristics}, {@link CaptureResult}, and

View File

@@ -64,47 +64,7 @@ public class CameraBinderDecorator {
// int return type => status_t => convert to exception
if (m.getReturnType() == Integer.TYPE) {
int returnValue = (Integer) result;
switch (returnValue) {
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:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DISCONNECTED));
case EACCES:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DISABLED));
case EBUSY:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_IN_USE));
case EUSERS:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
MAX_CAMERAS_IN_USE));
case ENODEV:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DISCONNECTED));
case EOPNOTSUPP:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DEPRECATED_HAL));
}
/**
* Trap the rest of the negative return values. If we have known
* error codes i.e. ALREADY_EXISTS that aren't really runtime
* errors, then add them to the top switch statement
*/
if (returnValue < 0) {
throw new UnsupportedOperationException(String.format("Unknown error %d",
returnValue));
}
throwOnError(returnValue);
}
}
@@ -130,6 +90,54 @@ public class CameraBinderDecorator {
}
/**
* Throw error codes returned by the camera service as exceptions.
*
* @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:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DISCONNECTED));
case EACCES:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DISABLED));
case EBUSY:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_IN_USE));
case EUSERS:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
MAX_CAMERAS_IN_USE));
case ENODEV:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DISCONNECTED));
case EOPNOTSUPP:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_DEPRECATED_HAL));
}
/**
* Trap the rest of the negative return values. If we have known
* error codes i.e. ALREADY_EXISTS that aren't really runtime
* errors, then add them to the top switch statement
*/
if (errorFlag < 0) {
throw new UnsupportedOperationException(String.format("Unknown error %d",
errorFlag));
}
}
/**
* <p>
* Wraps the type T with a proxy that will check 'status_t' return codes

View File

@@ -19,13 +19,18 @@
// #define LOG_NNDEBUG 0
#define LOG_TAG "CameraMetadata-JNI"
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <string.h>
#include "jni.h"
#include "JNIHelp.h"
#include "android_os_Parcel.h"
#include "android_runtime/AndroidRuntime.h"
#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.h>
#include <camera/ICameraService.h>
#include <camera/VendorTagDescriptor.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>
@@ -112,6 +117,7 @@ extern "C" {
static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
@@ -372,6 +378,9 @@ static JNINativeMethod gCameraMetadataMethods[] = {
{ "nativeGetTypeFromTag",
"(I)I",
(void *)CameraMetadata_getTypeFromTag },
{ "nativeSetupGlobalVendorTagDescriptor",
"()I",
(void*)CameraMetadata_setupGlobalVendorTagDescriptor },
// instance methods
{ "nativeAllocate",
"()J",
@@ -556,4 +565,29 @@ static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag) {
return tagType;
}
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
const String16 NAME("media.camera");
sp<ICameraService> cameraService;
status_t err = getService(NAME, /*out*/&cameraService);
if (err != OK) {
ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
strerror(-err), err);
return err;
}
sp<VendorTagDescriptor> desc;
err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
if (err != OK) {
ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)", __FUNCTION__,
strerror(-err), err);
return err;
}
err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
return err;
}
} // extern "C"