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

Commit ab98a0b1 authored by Igor Murashkin's avatar Igor Murashkin Committed by Android (Google) Code Review
Browse files

Merge "camera2: Add more camera device states, make #openCamera async." into klp-dev

parents 47d620ac 5c9eaf67
Loading
Loading
Loading
Loading
+22 −16
Original line number Diff line number Diff line
@@ -10840,22 +10840,20 @@ package android.hardware.camera2 {
    ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable);
    ctor public CameraAccessException(int, java.lang.Throwable);
    method public final int getReason();
    field public static final int CAMERA_DISABLED = 3; // 0x3
    field public static final int CAMERA_DISCONNECTED = 4; // 0x4
    field public static final int CAMERA_IN_USE = 1; // 0x1
    field public static final int MAX_CAMERAS_IN_USE = 2; // 0x2
    field public static final int CAMERA_DISABLED = 1; // 0x1
    field public static final int CAMERA_DISCONNECTED = 2; // 0x2
    field public static final int CAMERA_ERROR = 3; // 0x3
  }
  public abstract interface CameraDevice implements java.lang.AutoCloseable {
    method public abstract void capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public abstract void captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public abstract void close() throws java.lang.Exception;
    method public abstract void close();
    method public abstract void configureOutputs(java.util.List<android.view.Surface>) throws android.hardware.camera2.CameraAccessException;
    method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
    method public abstract void flush() throws android.hardware.camera2.CameraAccessException;
    method public abstract java.lang.String getId();
    method public abstract android.hardware.camera2.CameraProperties getProperties() throws android.hardware.camera2.CameraAccessException;
    method public abstract void setDeviceListener(android.hardware.camera2.CameraDevice.CameraDeviceListener, android.os.Handler);
    method public abstract void setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public abstract void setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
@@ -10866,15 +10864,6 @@ package android.hardware.camera2 {
    field public static final int TEMPLATE_VIDEO_SNAPSHOT = 4; // 0x4
  }
  public static abstract class CameraDevice.CameraDeviceListener {
    ctor public CameraDevice.CameraDeviceListener();
    method public void onCameraDisconnected(android.hardware.camera2.CameraDevice);
    method public void onCameraError(android.hardware.camera2.CameraDevice, int);
    method public void onCameraIdle(android.hardware.camera2.CameraDevice);
    field public static final int ERROR_CAMERA_DEVICE = 1; // 0x1
    field public static final int ERROR_CAMERA_SERVICE = 2; // 0x2
  }
  public static abstract class CameraDevice.CaptureListener {
    ctor public CameraDevice.CaptureListener();
    method public void onCaptureCompleted(android.hardware.camera2.CameraDevice, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
@@ -10882,11 +10871,28 @@ package android.hardware.camera2 {
    method public void onCaptureStarted(android.hardware.camera2.CameraDevice, android.hardware.camera2.CaptureRequest, long);
  }
  public static abstract class CameraDevice.StateListener {
    ctor public CameraDevice.StateListener();
    method public void onActive(android.hardware.camera2.CameraDevice);
    method public void onBusy(android.hardware.camera2.CameraDevice);
    method public void onClosed(android.hardware.camera2.CameraDevice);
    method public abstract void onDisconnected(android.hardware.camera2.CameraDevice);
    method public abstract void onError(android.hardware.camera2.CameraDevice, int);
    method public void onIdle(android.hardware.camera2.CameraDevice);
    method public abstract void onOpened(android.hardware.camera2.CameraDevice);
    method public void onUnconfigured(android.hardware.camera2.CameraDevice);
    field public static final int ERROR_CAMERA_DEVICE = 4; // 0x4
    field public static final int ERROR_CAMERA_DISABLED = 3; // 0x3
    field public static final int ERROR_CAMERA_IN_USE = 1; // 0x1
    field public static final int ERROR_CAMERA_SERVICE = 5; // 0x5
    field public static final int ERROR_MAX_CAMERAS_IN_USE = 2; // 0x2
  }
  public final class CameraManager {
    method public void addAvailabilityListener(android.hardware.camera2.CameraManager.AvailabilityListener, android.os.Handler);
    method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
    method public android.hardware.camera2.CameraProperties getCameraProperties(java.lang.String) throws android.hardware.camera2.CameraAccessException;
    method public android.hardware.camera2.CameraDevice openCamera(java.lang.String) throws android.hardware.camera2.CameraAccessException;
    method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public void removeAvailabilityListener(android.hardware.camera2.CameraManager.AvailabilityListener);
  }
+30 −10
Original line number Diff line number Diff line
@@ -29,22 +29,24 @@ import android.util.AndroidException;
public class CameraAccessException extends AndroidException {
    /**
     * The camera device is in use already
     * @hide
     */
    public static final int CAMERA_IN_USE = 1;
    public static final int CAMERA_IN_USE = 4;

    /**
     * The system-wide limit for number of open cameras has been reached,
     * and more camera devices cannot be opened until previous instances are
     * closed.
     * @hide
     */
    public static final int MAX_CAMERAS_IN_USE = 2;
    public static final int MAX_CAMERAS_IN_USE = 5;

    /**
     * The camera is disabled due to a device policy, and cannot be opened.
     *
     * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
     */
    public static final int CAMERA_DISABLED = 3;
    public static final int CAMERA_DISABLED = 1;

    /**
     * The camera device is removable and has been disconnected from the Android
@@ -52,7 +54,23 @@ public class CameraAccessException extends AndroidException {
     * is no longer valid, or the camera service has shut down the connection due to a
     * higher-priority access request for the camera device.
     */
    public static final int CAMERA_DISCONNECTED = 4;
    public static final int CAMERA_DISCONNECTED = 2;

    /**
     * The camera device is currently in the error state.
     *
     * <p>The camera has failed to open or has failed at a later time
     * as a result of some non-user interaction. Refer to
     * {@link CameraDevice.StateListener#onError} for the exact
     * nature of the error.</p>
     *
     * <p>No further calls to the camera will succeed. Clean up
     * the camera with {@link CameraDevice#close} and try
     * handling the error in order to successfully re-open the camera.
     * </p>
     *
     */
    public static final int CAMERA_ERROR = 3;

    /**
     * A deprecated HAL version is in use.
@@ -68,10 +86,9 @@ public class CameraAccessException extends AndroidException {
    /**
     * The reason for the failure to access the camera.
     *
     * @see #CAMERA_IN_USE
     * @see #MAX_CAMERAS_IN_USE
     * @see #CAMERA_DISABLED
     * @see #CAMERA_DISCONNECTED
     * @see #CAMERA_ERROR
     */
    public final int getReason() {
        return mReason;
@@ -105,12 +122,15 @@ public class CameraAccessException extends AndroidException {
                return "The system-wide limit for number of open cameras has been reached, " +
                       "and more camera devices cannot be opened until previous instances " +
                       "are closed.";
            case CAMERA_DISCONNECTED:
                return "The camera device is removable and has been disconnected from the " +
                        "Android device, or the camera service has shut down the connection due " +
                        "to a higher-priority access request for the camera device.";
            case CAMERA_DISABLED:
                return "The camera is disabled due to a device policy, and cannot be opened.";
            case CAMERA_DISCONNECTED:
                return "The camera device is removable and has been disconnected from the Android" +
                       " device, or the camera service has shut down the connection due to a " +
                       "higher-priority access request for the camera device.";
            case CAMERA_ERROR:
                return "The camera device is currently in the error state; " +
                       "no further calls to it will succeed.";
        }
        return null;
    }
+236 −61

File changed.

Preview size limit exceeded, changes collapsed.

+78 −4
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ public final class CameraManager {
    private final ICameraService mCameraService;
    private ArrayList<String> mDeviceIdList;

    private ArrayMap<AvailabilityListener, Handler> mListenerMap =
    private final ArrayMap<AvailabilityListener, Handler> mListenerMap =
            new ArrayMap<AvailabilityListener, Handler>();

    private final Context mContext;
@@ -201,8 +201,7 @@ public final class CameraManager {
     * @see #getCameraIdList
     * @see android.app.admin.DevicePolicyManager#setCameraDisabled
     */
    public CameraDevice openCamera(String cameraId) throws CameraAccessException {

    private CameraDevice openCamera(String cameraId) throws CameraAccessException {
        try {

            synchronized (mLock) {
@@ -236,6 +235,79 @@ public final class CameraManager {
        }
    }

    /**
     * Open a connection to a camera with the given ID.
     *
     * <p>Use {@link #getCameraIdList} to get the list of available camera
     * devices. Note that even if an id is listed, open may fail if the device
     * is disconnected between the calls to {@link #getCameraIdList} and
     * {@link #openCamera}.</p>
     *
     * <p>If the camera successfully opens after this function call returns,
     * {@link CameraDevice.StateListener#onOpened} will be invoked with the
     * newly opened {@link CameraDevice} in the unconfigured state.</p>
     *
     * <p>If the camera becomes disconnected during initialization
     * after this function call returns,
     * {@link CameraDevice.StateListener#onDisconnected} with a
     * {@link CameraDevice} in the disconnected state (and
     * {@link CameraDevice.StateListener#onOpened} will be skipped).</p>
     *
     * <p>If the camera fails to initialize after this function call returns,
     * {@link CameraDevice.StateListener#onError} will be invoked with a
     * {@link CameraDevice} in the error state (and
     * {@link CameraDevice.StateListener#onOpened} will be skipped).</p>
     *
     * @param cameraId
     *             The unique identifier of the camera device to open
     * @param listener
     *             The listener which is invoked once the camera is opened
     * @param handler
     *             The handler on which the listener should be invoked, or
     *             {@code null} to use the current thread's {@link android.os.Looper looper}.
     *
     * @throws CameraAccessException if the camera is disabled by device policy,
     * or the camera has become or was disconnected.
     *
     * @throws IllegalArgumentException if cameraId or the listener was null,
     * or the cameraId does not match any currently or previously available
     * camera device.
     *
     * @throws SecurityException if the application does not have permission to
     * access the camera
     *
     * @see #getCameraIdList
     * @see android.app.admin.DevicePolicyManager#setCameraDisabled
     */
    public void openCamera(String cameraId, final CameraDevice.StateListener listener,
            Handler handler)
            throws CameraAccessException {

        if (cameraId == null) {
            throw new IllegalArgumentException("cameraId was null");
        } else if (listener == null) {
            throw new IllegalArgumentException("listener was null");
        } else if (handler == null) {
            if (Looper.myLooper() != null) {
                handler = new Handler();
            } else {
                throw new IllegalArgumentException(
                        "Looper doesn't exist in the calling thread");
            }
        }

        final CameraDevice camera = openCamera(cameraId);
        camera.setDeviceListener(listener, handler);

        // TODO: make truly async in the camera service
        handler.post(new Runnable() {
            @Override
            public void run() {
                listener.onOpened(camera);
            }
        });
    }

    /**
     * Interface for listening to camera devices becoming available or
     * unavailable.
@@ -265,7 +337,7 @@ public final class CameraManager {
         *
         * <p>If an application had an active CameraDevice instance for the
         * now-disconnected camera, that application will receive a
         * {@link CameraDevice.CameraDeviceListener#onCameraDisconnected disconnection error}.</p>
         * {@link CameraDevice.StateListener#onDisconnected disconnection error}.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
@@ -403,6 +475,7 @@ public final class CameraManager {
                    if (isAvailable(status)) {
                        handler.post(
                            new Runnable() {
                                @Override
                                public void run() {
                                    listener.onCameraAvailable(id);
                                }
@@ -410,6 +483,7 @@ public final class CameraManager {
                    } else {
                        handler.post(
                            new Runnable() {
                                @Override
                                public void run() {
                                    listener.onCameraUnavailable(id);
                                }
+4 −6
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
    private final Object mLock = new Object();
    private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();

    private CameraDeviceListener mDeviceListener;
    private StateListener mDeviceListener;
    private Handler mDeviceHandler;

    private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
@@ -292,7 +292,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
    }

    @Override
    public void setDeviceListener(CameraDeviceListener listener, Handler handler) {
    public void setDeviceListener(StateListener listener, Handler handler) {
        synchronized (mLock) {
            mDeviceListener = listener;
            mDeviceHandler = handler;
@@ -314,7 +314,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
    }

    @Override
    public void close() throws Exception {
    public void close() {

        // TODO: every method should throw IllegalStateException after close has been called

@@ -325,7 +325,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
                    mRemoteDevice.disconnect();
                }
            } catch (CameraRuntimeException e) {
                throw e.asChecked();
                Log.e(TAG, "Exception while closing: ", e.asChecked());
            } catch (RemoteException e) {
                // impossible
            }
@@ -339,8 +339,6 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
    protected void finalize() throws Throwable {
        try {
            close();
        } catch (CameraRuntimeException e) {
            Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
        }
        finally {
            super.finalize();