Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d3c318b authored by Wu-cheng Li's avatar Wu-cheng Li Committed by Android (Google) Code Review
Browse files

Merge "Add a new camera open API that allows taking the ownership."

parents 0c269766 a1c41e13
Loading
Loading
Loading
Loading
+76 −8
Original line number Diff line number Diff line
@@ -236,6 +236,50 @@ public class Camera {
    /**
     * Creates a new Camera object to access a particular hardware camera.
     *
     * <p>When <code>force</code> is set to false, this will throw an exception
     * if the same camera is already opened by other clients. If true, the other
     * client will be disconnected from the camera they opened. If the device
     * can only support one camera running at a time, all camera-using clients
     * will be disconnected from their cameras.
     *
     * <p>A camera being held by an application can be taken away by other
     * applications at any time. Before the camera is taken, applications will
     * get {@link #CAMERA_ERROR_RELEASED} and have some time to clean up. Apps
     * receiving this callback must immediately stop video recording and then
     * call {@link #release()} on their camera object. Otherwise, it will be
     * released by the frameworks in a short time. After receiving
     * CAMERA_ERROR_RELEASED, apps should not call any method except <code>
     * release</code> and {@link #isReleased()}. After a camera is taken away,
     * all methods will throw exceptions except <code>isReleased</code> and
     * <code>release</code>. Apps can use <code>isReleased</code> to see if the
     * camera has been taken away. If the camera is taken away, the apps can
     * silently finish themselves or show a dialog.
     *
     * <p>Applications with android.permission.KEEP_CAMERA can request to keep
     * the camera. That is, the camera will not be taken by other applications
     * while it is opened. The permission can only be obtained by trusted
     * platform applications, such as those implementing lock screen security
     * features.
     *
     * @param cameraId the hardware camera to access, between 0 and
     *     {@link #getNumberOfCameras()}-1.
     * @param force true to take the ownership from the existing client if the
     *     camera has been opened by other clients.
     * @param keep true if the applications do not want other apps to take the
     *     camera. Only the apps with android.permission.KEEP_CAMERA can keep
     *     the camera.
     * @return a new Camera object, connected, locked and ready for use.
     * @hide
     */
    public static Camera open(int cameraId, boolean force, boolean keep) {
        return new Camera(cameraId, force, keep);
    }

    /**
     * Creates a new Camera object to access a particular hardware camera. If
     * the same camera is opened by other applications, 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.
     *
@@ -255,13 +299,13 @@ public class Camera {
     * @param cameraId the hardware camera to access, between 0 and
     *     {@link #getNumberOfCameras()}-1.
     * @return a new Camera object, connected, locked and ready for use.
     * @throws RuntimeException if connection to the camera service fails (for
     *     example, if the camera is in use by another process or device policy
     *     manager has disabled the camera).
     * @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)
     */
    public static Camera open(int cameraId) {
        return new Camera(cameraId);
        return new Camera(cameraId, false, false);
    }

    /**
@@ -276,13 +320,13 @@ public class Camera {
        for (int i = 0; i < numberOfCameras; i++) {
            getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                return new Camera(i);
                return new Camera(i, false, false);
            }
        }
        return null;
    }

    Camera(int cameraId) {
    Camera(int cameraId, boolean force, boolean keep) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
@@ -299,7 +343,7 @@ public class Camera {
            mEventHandler = null;
        }

        native_setup(new WeakReference<Camera>(this), cameraId);
        native_setup(new WeakReference<Camera>(this), cameraId, force, keep);
    }

    /**
@@ -312,7 +356,8 @@ public class Camera {
        release();
    }

    private native final void native_setup(Object camera_this, int cameraId);
    private native final void native_setup(Object camera_this, int cameraId,
            boolean force, boolean keep);
    private native final void native_release();


@@ -326,6 +371,18 @@ public class Camera {
        mFaceDetectionRunning = false;
    }

    /**
     * Whether the camera is released. When any camera method throws an
     * exception, applications can use this to check whether the camera has been
     * taken by other clients. If true, it means other clients have taken the
     * camera. The applications can silently finish themselves or show a dialog.
     *
     * @return whether the camera is released.
     * @see #open(int, boolean, boolean)
     * @hide
     */
    public native final boolean isReleased();

    /**
     * Unlocks the camera to allow another process to access it.
     * Normally, the camera is locked to the process with an active Camera
@@ -1321,6 +1378,17 @@ public class Camera {
     */
    public static final int CAMERA_ERROR_UNKNOWN = 1;

    /**
     * Camera was released because another client has opened the camera. The
     * application should call {@link #release()} after getting this. The apps
     * should not call any method except <code>release</code> and {@link #isReleased()}
     * after this.
     *
     * @see Camera.ErrorCallback
     * @hide
     */
    public static final int CAMERA_ERROR_RELEASED = 2;

    /**
     * Media server died. In this case, the application must release the
     * Camera object and instantiate a new one.
+21 −4
Original line number Diff line number Diff line
@@ -457,9 +457,9 @@ static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,

// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId)
    jobject weak_this, jint cameraId, jboolean force, jboolean keep)
{
    sp<Camera> camera = Camera::connect(cameraId);
    sp<Camera> camera = Camera::connect(cameraId, force, keep);

    if (camera == NULL) {
        jniThrowRuntimeException(env, "Fail to connect to camera service");
@@ -700,7 +700,12 @@ static jstring android_hardware_Camera_getParameters(JNIEnv *env, jobject thiz)
    sp<Camera> camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return 0;

    return env->NewStringUTF(camera->getParameters().string());
    String8 params8 = camera->getParameters();
    if (params8.isEmpty()) {
        jniThrowRuntimeException(env, "getParameters failed (empty parameters)");
        return 0;
    }
    return env->NewStringUTF(params8.string());
}

static void android_hardware_Camera_reconnect(JNIEnv *env, jobject thiz)
@@ -816,6 +821,15 @@ static void android_hardware_Camera_enableFocusMoveCallback(JNIEnv *env, jobject
    }
}

static bool android_hardware_Camera_isReleased(JNIEnv *env, jobject thiz)
{
    ALOGV("isReleased");
    sp<Camera> camera = get_native_camera(env, thiz, NULL);
    if (camera == 0) return true;

    return (camera->sendCommand(CAMERA_CMD_PING, 0, 0) != NO_ERROR);
}

//-------------------------------------------------

static JNINativeMethod camMethods[] = {
@@ -826,7 +840,7 @@ static JNINativeMethod camMethods[] = {
    "(ILandroid/hardware/Camera$CameraInfo;)V",
    (void*)android_hardware_Camera_getCameraInfo },
  { "native_setup",
    "(Ljava/lang/Object;I)V",
    "(Ljava/lang/Object;IZZ)V",
    (void*)android_hardware_Camera_native_setup },
  { "native_release",
    "()V",
@@ -894,6 +908,9 @@ static JNINativeMethod camMethods[] = {
  { "enableFocusMoveCallback",
    "(I)V",
    (void *)android_hardware_Camera_enableFocusMoveCallback},
  { "isReleased",
    "()Z",
    (void *)android_hardware_Camera_isReleased},
};

struct field {
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ public:
    static  int32_t     getNumberOfCameras();
    static  status_t    getCameraInfo(int cameraId,
                                      struct CameraInfo* cameraInfo);
    static  sp<Camera>  connect(int cameraId);
    static  sp<Camera>  connect(int cameraId, bool force, bool keep);
            virtual     ~Camera();
            void        init();

+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ public:
    virtual status_t        getCameraInfo(int cameraId,
                                          struct CameraInfo* cameraInfo) = 0;
    virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient,
                                    int cameraId) = 0;
                                    int cameraId, bool force, bool keep) = 0;
};

// ----------------------------------------------------------------------------
+2 −2
Original line number Diff line number Diff line
@@ -116,13 +116,13 @@ status_t Camera::getCameraInfo(int cameraId,
    return cs->getCameraInfo(cameraId, cameraInfo);
}

sp<Camera> Camera::connect(int cameraId)
sp<Camera> Camera::connect(int cameraId, bool force, bool keep)
{
    ALOGV("connect");
    sp<Camera> c = new Camera();
    const sp<ICameraService>& cs = getCameraService();
    if (cs != 0) {
        c->mCamera = cs->connect(c, cameraId);
        c->mCamera = cs->connect(c, cameraId, force, keep);
    }
    if (c->mCamera != 0) {
        c->mCamera->asBinder()->linkToDeath(c);
Loading