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

Commit feb50af3 authored by Ruben Brunk's avatar Ruben Brunk
Browse files

camera2: Add HAL1 compatibility shim skeleton.

This adds basic support for running the Camera2 API on a device running
a camera HAL version lower than CAMERA_MODULE_API_VERSION_2_0.

This CL includes support for:
- N-way preview output streams
- N-way jpeg output streams
- CameraDevice emulation at the binder interface
- Basic camera metadata querying in the CameraManager

Bug: 15117269
Bug: 15116722

Change-Id: I8322955034c91f34bb348d4b28c2b774dbef38f6
parent 2a2dace6
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -169,6 +169,10 @@ public class Camera {
    private boolean mFaceDetectionRunning = false;
    private Object mAutoFocusCallbackLock = new Object();

    private static final int NO_ERROR = 0;
    private static final int EACCESS = -13;
    private static final int ENODEV = -19;

    /**
     * Broadcast Action:  A new picture is taken by the camera, and the entry of
     * the picture has been added to the media store.
@@ -328,6 +332,24 @@ public class Camera {
    }

    Camera(int cameraId) {
        int err = cameraInit(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");
            }
        }
    }

    /**
     * @hide
     */
    public int cameraInit(int cameraId) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
@@ -347,7 +369,21 @@ public class Camera {

        String packageName = ActivityThread.currentPackageName();

        native_setup(new WeakReference<Camera>(this), cameraId, packageName);
        return native_setup(new WeakReference<Camera>(this), cameraId, packageName);
    }

    /**
     * @hide
     */
    public static boolean checkInitErrors(int err) {
        return err != NO_ERROR;
    }

    /**
     * @hide
     */
    public static Camera openUninitialized() {
        return new Camera();
    }

    /**
@@ -360,7 +396,7 @@ public class Camera {
        release();
    }

    private native final void native_setup(Object camera_this, int cameraId,
    private native final int native_setup(Object camera_this, int cameraId,
                                           String packageName);

    private native final void native_release();
@@ -458,13 +494,16 @@ public class Camera {
     */
    public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
        if (holder != null) {
            setPreviewDisplay(holder.getSurface());
            setPreviewSurface(holder.getSurface());
        } else {
            setPreviewDisplay((Surface)null);
            setPreviewSurface((Surface)null);
        }
    }

    private native final void setPreviewDisplay(Surface surface) throws IOException;
    /**
     * @hide
     */
    public native final void setPreviewSurface(Surface surface) throws IOException;

    /**
     * Sets the {@link SurfaceTexture} to be used for live preview.
+18 −5
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.hardware.ICameraService;
import android.hardware.ICameraServiceListener;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.legacy.CameraDeviceUserShim;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.hardware.camera2.utils.BinderHolder;
@@ -194,7 +195,6 @@ public final class CameraManager {
            // impossible
            return null;
        }

        return new CameraCharacteristics(info);
    }

@@ -236,10 +236,23 @@ public final class CameraManager {
                                handler);

                BinderHolder holder = new BinderHolder();
                mCameraService.connectDevice(device.getCallbacks(),
                        Integer.parseInt(cameraId),
                        mContext.getPackageName(), USE_CALLING_UID, holder);

                ICameraDeviceCallbacks callbacks = device.getCallbacks();
                int id = Integer.parseInt(cameraId);
                try {
                    mCameraService.connectDevice(callbacks, id, mContext.getPackageName(),
                            USE_CALLING_UID, holder);
                    cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
                } catch (CameraRuntimeException e) {
                    if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
                        // Use legacy camera implementation for HAL1 devices
                        Log.i(TAG, "Using legacy camera HAL.");
                        cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
                    } else {
                        // Rethrow otherwise
                        throw e;
                    }
                }

                // TODO: factor out listener to be non-nested, then move setter to constructor
                // For now, calling setRemoteDevice will fire initial
+16 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.os.Parcelable;
import android.util.Rational;
import android.view.Surface;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;

@@ -198,6 +200,20 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable {
        dest.writeParcelableArray(mSurfaceSet.toArray(new Surface[mSurfaceSet.size()]), flags);
    }

    /**
     * @hide
     */
    public boolean containsTarget(Surface surface) {
        return mSurfaceSet.contains(surface);
    }

    /**
     * @hide
     */
    public Collection<Surface> getTargets() {
        return Collections.unmodifiableCollection(mSurfaceSet);
    }

    /**
     * A builder for capture requests.
     *
+23 −1
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ import android.hardware.camera2.utils.LongParcelable;
interface ICameraDeviceUser
{
    /**
     * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h
     * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h and
     * frameworks/base/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
     */
    void disconnect();

@@ -41,6 +42,27 @@ interface ICameraDeviceUser

    int cancelRequest(int requestId, out LongParcelable lastFrameNumber);

    /**
     * Begin the device configuration.
     *
     * <p>
     * beginConfigure must be called before any call to deleteStream, createStream,
     * or endConfigure.  It is not valid to call this when the device is not idle.
     * <p>
     */
    int beginConfigure();

    /**
     * End the device configuration.
     *
     * <p>
     * endConfigure must be called after stream configuration is complete (i.e. after
     * a call to beginConfigure and subsequent createStream/deleteStream calls).  This
     * must be called before any requests can be submitted.
     * <p>
     */
    int endConfigure();

    int deleteStream(int streamId);

    // non-negative value is the stream ID. negative value is status_t
+2 −2
Original line number Diff line number Diff line
@@ -216,7 +216,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
            try {
                waitUntilIdle();

                // TODO: mRemoteDevice.beginConfigure
                mRemoteDevice.beginConfigure();
                // Delete all streams first (to free up HW resources)
                for (Integer streamId : deleteList) {
                    mRemoteDevice.deleteStream(streamId);
@@ -231,7 +231,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
                    mConfiguredOutputs.put(streamId, s);
                }

                // TODO: mRemoteDevice.endConfigure
                mRemoteDevice.endConfigure();
            } catch (CameraRuntimeException e) {
                if (e.getReason() == CAMERA_IN_USE) {
                    throw new IllegalStateException("The camera is currently busy." +
Loading