diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/hardware/Camera.java | 131 | ||||
-rw-r--r-- | core/java/android/hardware/ICameraService.aidl | 7 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 19 |
3 files changed, 150 insertions, 7 deletions
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 0705e0c..44fc3b6 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -172,6 +172,11 @@ public class Camera { 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 @@ -190,6 +195,22 @@ public class Camera { public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; /** + * Camera HAL device API version 1.0 + * @hide + */ + public static final int CAMERA_HAL_API_VERSION_1_0 = 0x100; + + /** + * A constant meaning the normal camera connect/open will be used. + * @hide + */ + public static final int CAMERA_HAL_API_VERSION_NORMAL_OPEN = -2; + + /** + * Used to indicate HAL version un-specified. + */ + private static final int CAMERA_HAL_API_VERSION_UNSPECIFIED = -1; + /** * Hardware face detection. It does not use much CPU. */ private static final int CAMERA_FACE_DETECTION_HW = 0; @@ -331,6 +352,111 @@ public class Camera { return null; } + /** + * Creates a new Camera object to access a particular hardware camera with + * given hal API version. If the same camera is opened by other applications + * or the hal API version is not supported by this device, this will throw a + * RuntimeException. + * <p> + * You must call {@link #release()} when you are done using the camera, + * otherwise it will remain locked and be unavailable to other applications. + * <p> + * Your application should only have one Camera object active at a time for + * a particular hardware camera. + * <p> + * Callbacks from other methods are delivered to the event loop of the + * thread which called open(). If this thread has no event loop, then + * callbacks are delivered to the main application event loop. If there is + * no main application event loop, callbacks are not delivered. + * <p class="caution"> + * <b>Caution:</b> On some devices, this method may take a long time to + * complete. It is best to call this method from a worker thread (possibly + * using {@link android.os.AsyncTask}) to avoid blocking the main + * application UI thread. + * + * @param cameraId The hardware camera to access, between 0 and + * {@link #getNumberOfCameras()}-1. + * @param halVersion The HAL API version this camera device to be opened as. When + * it is {@value #CAMERA_HAL_API_VERSION_NORMAL_OPEN}, the methods will be equivalent + * to {@link #open}, but more detailed error information will be returned to managed code. + * @return a new Camera object, connected, locked and ready for use. + * @throws RuntimeException if opening the camera fails (for example, if the + * camera is in use by another process or device policy manager has disabled + * the camera). + * @see android.app.admin.DevicePolicyManager#getCameraDisabled(android.content.ComponentName) + * + * @hide + */ + public static Camera openLegacy(int cameraId, int halVersion) { + return new Camera(cameraId, halVersion); + } + + /** + * Create a legacy camera object. + * + * @param cameraId The hardware camera to access, between 0 and + * {@link #getNumberOfCameras()}-1. + * @param halVersion The HAL API version this camera device to be opened as. + */ + private Camera(int cameraId, int halVersion) { + int err = cameraInit(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"); + } + } + } + + private int cameraInit(int cameraId, int halVersion) { + // This function should be only called by Camera(int cameraId, int halVersion). + if (halVersion < CAMERA_HAL_API_VERSION_1_0 && + halVersion != CAMERA_HAL_API_VERSION_NORMAL_OPEN) { + throw new IllegalArgumentException("Invalid HAL version " + halVersion); + } + + mShutterCallback = null; + mRawImageCallback = null; + mJpegCallback = null; + mPreviewCallback = null; + mPostviewCallback = null; + mUsingPreviewAllocation = false; + mZoomListener = null; + + Looper looper; + if ((looper = Looper.myLooper()) != null) { + mEventHandler = new EventHandler(this, looper); + } else if ((looper = Looper.getMainLooper()) != null) { + mEventHandler = new EventHandler(this, looper); + } else { + mEventHandler = null; + } + + String packageName = ActivityThread.currentPackageName(); + + return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName); + } + Camera(int cameraId) { int err = cameraInit(cameraId); if (checkInitErrors(err)) { @@ -369,7 +495,8 @@ public class Camera { String packageName = ActivityThread.currentPackageName(); - return native_setup(new WeakReference<Camera>(this), cameraId, packageName); + return native_setup(new WeakReference<Camera>(this), cameraId, + CAMERA_HAL_API_VERSION_UNSPECIFIED, packageName); } /** @@ -396,7 +523,7 @@ public class Camera { release(); } - private native final int native_setup(Object camera_this, int cameraId, + private native final int native_setup(Object camera_this, int cameraId, int halVersion, String packageName); private native final void native_release(); diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl index 31896f5..2bc3dd4 100644 --- a/core/java/android/hardware/ICameraService.aidl +++ b/core/java/android/hardware/ICameraService.aidl @@ -74,4 +74,11 @@ interface ICameraService int getLegacyParameters(int cameraId, out String[] parameters); // Determines if a particular API version is supported; see ICameraService.h for version defines int supportsCameraApi(int cameraId, int apiVersion); + + int connectLegacy(ICameraClient client, int cameraId, + int halVersion, + String clientPackageName, + int clientUid, + // Container for an ICamera object + out BinderHolder device); } diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 3a53331..4c9feca 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -466,7 +466,7 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz, // connect to camera service static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, - jobject weak_this, jint cameraId, jstring clientPackageName) + jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) { // Convert jstring to String16 const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL); @@ -474,8 +474,18 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, String16 clientName(rawClientName, rawClientNameLen); env->ReleaseStringChars(clientPackageName, rawClientName); - sp<Camera> camera = Camera::connect(cameraId, clientName, - Camera::USE_CALLING_UID); + sp<Camera> camera; + if (halVersion == ICameraService::CAMERA_HAL_API_VERSION_UNSPECIFIED) { + // Default path: hal version is unspecified, do normal camera open. + camera = Camera::connect(cameraId, clientName, + Camera::USE_CALLING_UID); + } else { + jint status = Camera::connectLegacy(cameraId, halVersion, clientName, + Camera::USE_CALLING_UID, camera); + if (status != NO_ERROR) { + return status; + } + } if (camera == NULL) { return -EACCES; @@ -510,7 +520,6 @@ static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, // finalizer is invoked later. static void android_hardware_Camera_release(JNIEnv *env, jobject thiz) { - // TODO: Change to ALOGV ALOGV("release camera"); JNICameraContext* context = NULL; sp<Camera> camera; @@ -891,7 +900,7 @@ static JNINativeMethod camMethods[] = { "(ILandroid/hardware/Camera$CameraInfo;)V", (void*)android_hardware_Camera_getCameraInfo }, { "native_setup", - "(Ljava/lang/Object;ILjava/lang/String;)I", + "(Ljava/lang/Object;IILjava/lang/String;)I", (void*)android_hardware_Camera_native_setup }, { "native_release", "()V", |