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

Commit c455927f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "OfflineReproc-impl"

* changes:
  Camera: Add API for surface offline mode queries
  Camera: Add initial offline camera session implementation
parents d12565dd 731009ed
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -17050,6 +17050,8 @@ package android.hardware.camera2 {
    method public abstract int setRepeatingRequest(@NonNull android.hardware.camera2.CaptureRequest, @Nullable android.hardware.camera2.CameraCaptureSession.CaptureCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public int setSingleRepeatingRequest(@NonNull android.hardware.camera2.CaptureRequest, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraCaptureSession.CaptureCallback) throws android.hardware.camera2.CameraAccessException;
    method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
    method public boolean supportsOfflineProcessing(@NonNull android.view.Surface);
    method @Nullable public android.hardware.camera2.CameraOfflineSession switchToOffline(@NonNull java.util.Collection<android.view.Surface>, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback) throws android.hardware.camera2.CameraAccessException;
    method public void updateOutputConfiguration(android.hardware.camera2.params.OutputConfiguration) throws android.hardware.camera2.CameraAccessException;
  }
@@ -17474,6 +17476,20 @@ package android.hardware.camera2 {
    field public static final int TONEMAP_PRESET_CURVE_SRGB = 0; // 0x0
  }
  public abstract class CameraOfflineSession extends android.hardware.camera2.CameraCaptureSession {
    ctor public CameraOfflineSession();
  }
  public abstract static class CameraOfflineSession.CameraOfflineSessionCallback {
    ctor public CameraOfflineSession.CameraOfflineSessionCallback();
    method public abstract void onClosed(@NonNull android.hardware.camera2.CameraOfflineSession);
    method public abstract void onError(@NonNull android.hardware.camera2.CameraOfflineSession, int);
    method public abstract void onIdle(@NonNull android.hardware.camera2.CameraOfflineSession);
    method public abstract void onReady(@NonNull android.hardware.camera2.CameraOfflineSession);
    method public abstract void onSwitchFailed(@NonNull android.hardware.camera2.CameraOfflineSession);
    field public static final int STATUS_INTERNAL_ERROR = 0; // 0x0
  }
  public class CaptureFailure {
    method public long getFrameNumber();
    method @Nullable public String getPhysicalCameraId();
+94 −0
Original line number Diff line number Diff line
@@ -19,10 +19,13 @@ package android.hardware.camera2;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.camera2.CameraOfflineSession;
import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
import android.hardware.camera2.params.OutputConfiguration;
import android.os.Handler;
import android.view.Surface;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;

@@ -854,6 +857,97 @@ public abstract class CameraCaptureSession implements AutoCloseable {
        throw new UnsupportedOperationException("Subclasses must override this method");
    }

    /**
     * Switch the current capture session and a given set of registered camera surfaces
     * to offline processing mode.
     *
     * <p>Offline processing mode and the corresponding {@link CameraOfflineSession} differ from
     * a regular online camera capture session in several ways. Successful offline switches will
     * close the currently active camera capture session. Camera clients are also allowed
     * to call {@link CameraDevice#close} while offline processing of selected capture
     * requests is still in progress. Such side effects free device close is only possible
     * when the offline session moves to the ready state. Once this happens, closing the camera
     * device will not affect the pending offline requests and they must complete as normal.</p>
     *
     * <p>Offline processing mode switches may need several hundred milliseconds to complete
     * as the underlying camera implementation must abort all currently active repeating requests
     * as well as all other pending requests not specified by the client. Additionally the switch
     * will be blocked until all requests that continue processing within the offline session
     * acquire their initial input frame from camera sensor. The call to {@link #switchToOffline}
     * itself is not blocking and will only trigger the offline switch sequence. Clients will
     * be notified via {@link CameraOfflineSessionCallback#onReady} once the entire sequence is
     * complete.</p>
     *
     * <p>Please note that after a successful call to this method the currently active capture
     * session will no longer be valid and clients will begin receiving capture
     * callbacks with a corresponding {@link CameraOfflineSession} passed as a session
     * argument.</p>
     *
     * @param offlineSurfaces Client-specified collection of input/output camera registered surfaces
     *                        that need to be switched to offline mode along with their pending
     *                        capture requests. Do note that not all camera registered
     *                        surfaces can be switched to offline mode. Offline processing
     *                        support for individual surfaces can be queried using
     *                        {@link #supportsOfflineProcessing}. Additionally offline mode
     *                        switches are not available for shared surfaces
     *                        {@link OutputConfiguration#enableSurfaceSharing} and surfaces
     *                        as part of a surface group.
     *
     * @param executor The executor which will be used for invoking the offline callback listener.
     *
     * @param listener The callback object to notify for offline session events.
     *
     * @return camera offline session which in case of successful offline switch will move in ready
     *         state after clients receive {@link CameraOfflineSessionCallback#onReady}. In case the
     *         offline switch was not successful clients will receive respective
     *         {@link CameraOfflineSessionCallback#onSwitchFailed} notification.
     *
     * @throws IllegalArgumentException if an attempt was made to pass a {@link Surface} that was
     *                                  not registered with this capture session or a shared
     *                                  surface {@link OutputConfiguration#enableSurfaceSharing} or
     *                                  surface as part of a surface group. The current capture
     *                                  session will remain valid and active in case of this
     *                                  exception.
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error.
     *
     * @see CameraOfflineSession
     * @see CameraOfflineSessionCallback
     * @see #supportsOfflineProcessing
     */
    @Nullable
    public CameraOfflineSession switchToOffline(@NonNull Collection<Surface> offlineSurfaces,
            @NonNull Executor executor, @NonNull CameraOfflineSessionCallback listener)
            throws CameraAccessException {
        throw new UnsupportedOperationException("Subclasses must override this method");
    }

    /**
     * <p>Query whether a given Surface is able to support offline mode. </p>
     *
     * <p>Surfaces that support offline mode can be passed as arguments to {@link #switchToOffline}.
     * </p>
     *
     * @param surface An input/output surface that was used to create this session or the result of
     *                {@link #getInputSurface}.
     *
     * @return {@code true} if the surface can support offline mode and can be passed as argument to
     *         {@link #switchToOffline}. {@code false} otherwise.
     *
     * @throws IllegalArgumentException if an attempt was made to pass a {@link Surface} that was
     *                                  not registered with this capture session.
     * @throws UnsupportedOperationException if an attempt was made to call this method using
     *                                       unsupported camera capture session like
     *                                       {@link CameraConstrainedHighSpeedCaptureSession} or
     *                                       {@link CameraOfflineSession}.
     *
     * @see #switchToOffline
     */
    public boolean supportsOfflineProcessing(@NonNull Surface surface) {
        throw new UnsupportedOperationException("Subclasses must override this method");
    }

    /**
     * Close this capture session asynchronously.
     *
+159 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.camera2;

import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;

import android.annotation.IntDef;
import android.annotation.NonNull;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * A camera capture session that was switched to offline mode via successful call to
 * {@link CameraCaptureSession#switchToOffline}.
 *
 * <p>Offline capture sessions allow clients to select a set of camera registered surfaces that
 * support offline mode.  After a successful offline mode switch all non-repeating pending requests
 * on those surfaces will continue to be processed by the camera stack even if clients close the
 * corresponding camera device.<p>
 *
 * <p>Offline capture session instances will replace the previously active capture session arguments
 * in all capture callbacks after {@link CameraCaptureSession#switchToOffline} completes.</p>
 *
 * <p>Processing of pending offline capture requests will begin only after the offline session
 * moves to ready state which will be indicated by the {@link CameraOfflineSessionCallback#onReady}
 * callback.</p>
 *
 * <p>In contrast to a regular {@link CameraCaptureSession} an offline capture session will
 * not accept any further capture requests. Besides {@link CameraOfflineSession#close} all
 * remaining methods will throw {@link UnsupportedOperationException} and are not supported.</p>
 *
 * @see CameraCaptureSession#supportsOfflineProcessing
 */
public abstract class CameraOfflineSession extends CameraCaptureSession {
    public static abstract class CameraOfflineSessionCallback {
        /**
         * This method indicates that the offline switch call
         * {@link CameraCaptureSession#switchToOffline} was successful.
         *
         * <p>This callback will be invoked once the offline session moves to the ready state.</p>
         *
         * <p>Calls to {@link CameraDevice#close} will not have impact on the processing of offline
         * requests once the offline session moves in ready state.</p>
         *
         * @param session the currently ready offline session
         *
         */
        public abstract void onReady(@NonNull CameraOfflineSession session);

        /**
         * This method indicates that the offline switch call
         * {@link CameraCaptureSession#switchToOffline} was not able to complete successfully.
         *
         * <p>The offline switch can fail either due to internal camera error during the switch
         * sequence or because the camera implementation was not able to find any pending capture
         * requests that can be migrated to offline mode.</p>
         *
         * <p>Calling {@link CameraOfflineSession#close} is not necessary and clients will not
         * receive any further offline session notifications.</p>
         *
         * @param session the offline session that failed to switch to ready state
         */
        public abstract void onSwitchFailed(@NonNull CameraOfflineSession session);

        /**
         * This method indicates that all pending offline requests were processed.
         *
         * <p>This callback will be invoked once the offline session finishes processing
         * all of its pending offline capture requests.</p>
         *
         * @param session the currently ready offline session
         *
         */
        public abstract void onIdle(@NonNull CameraOfflineSession session);

        /**
         * This status code indicates unexpected and fatal internal camera error.
         *
         * <p>Pending offline requests will be discarded and the respective registered
         * capture callbacks may not get triggered.</p>
         *
         * @see #onError
         */
        public static final int STATUS_INTERNAL_ERROR = 0;

        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(prefix = {"STATUS_"}, value = {STATUS_INTERNAL_ERROR})
        public @interface StatusCode {};

        /**
         * This method is called when the offline session encounters an unexpected error.
         *
         * <p>This notification will only be invoked for sessions that reached the ready state.
         * Clients will need to call {@link CameraOfflineSession#close} to close and release all
         * resources. {@link #onClosed} will not be triggered automatically in error scenarios.</p>
         *
         * @param session the current offline session
         * @param status error status
         *
         */
        public abstract void onError(@NonNull CameraOfflineSession session, @StatusCode int status);

        /**
         * This method is called when the offline session is closed.
         *
         * <p>An offline session will be closed after a call to
         * {@link CameraOfflineSession#close}.</p>
         *
         * <p>In case of failure to switch to offline mode, only {@link #onSwitchFailed} will be
         * called and {@link #onClosed} will not be.</p>
         *
         * <p>In case there was no previous {@link #onIdle} notification any in-progress
         * offline capture requests within the offline session will be discarded
         * and further result callbacks will not be triggered.</p>
         *
         * @param session the session returned by {@link CameraCaptureSession#switchToOffline}
         *
         */
        public abstract void onClosed(@NonNull CameraOfflineSession session);
    }

    /**
     * Close this offline capture session.
     *
     * <p>Abort all pending offline requests and close the connection to the offline camera session
     * as quickly as possible.</p>
     *
     * <p>This method can be called only after clients receive
     * {@link CameraOfflineSessionCallback#onReady}.</p>
     *
     * <p>Immediately after this call, besides the final
     * {@link CameraOfflineSessionCallback#onClosed} notification, no further callbacks from the
     * offline session will be triggered and all remaining offline capture requests will be
     * discarded.</p>
     *
     * <p>Closing a session is idempotent; closing more than once has no effect.</p>
     *
     * @throws IllegalStateException if the offline sesion is not ready.
     */
    @Override
    public abstract void close();
}
+10 −0
Original line number Diff line number Diff line
@@ -61,4 +61,14 @@ public interface CameraCaptureSessionCore {
     */
    boolean isAborting();

    /**
     * Close the capture session without draining the pending requests.
     *
     * <p>This is usually used when switching to offline session mode. Depending
     * on the client input, some of the pending requests will be flushed and some
     * will remain for further processing. In either case, the regular drain logic
     * needs to be skipped.</p>
     *
     */
    void closeWithoutDraining();
}
+62 −10
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package android.hardware.camera2.impl;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraOfflineSession;
import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.params.OutputConfiguration;
@@ -29,6 +31,7 @@ import android.util.Log;
import android.view.Surface;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;

@@ -106,7 +109,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
         * Use the same handler as the device's StateCallback for all the internal coming events
         *
         * This ensures total ordering between CameraDevice.StateCallback and
         * CameraDeviceImpl.CaptureCallback events.
         * CaptureCallback events.
         */
        mSequenceDrainer = new TaskDrainer<>(mDeviceExecutor, new SequenceDrainListener(),
                /*name*/"seq");
@@ -136,24 +139,36 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession

    @Override
    public void prepare(Surface surface) throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();
            mDeviceImpl.prepare(surface);
        }
    }

    @Override
    public void prepare(int maxCount, Surface surface) throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();
            mDeviceImpl.prepare(maxCount, surface);
        }
    }

    @Override
    public void tearDown(Surface surface) throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();
            mDeviceImpl.tearDown(surface);
        }
    }

    @Override
    public void finalizeOutputConfigurations(
            List<OutputConfiguration> outputConfigs) throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();
            mDeviceImpl.finalizeOutputConfigs(outputConfigs);
        }
    }

    @Override
    public int capture(CaptureRequest request, CaptureCallback callback,
@@ -445,6 +460,24 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
        }
    }

    @Override
    public CameraOfflineSession switchToOffline(Collection<Surface> offlineOutputs,
            Executor executor, CameraOfflineSessionCallback listener) throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();
        }
        return mDeviceImpl.switchToOffline(offlineOutputs, executor, listener);
    }


    @Override
    public boolean supportsOfflineProcessing(Surface surface) {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();
        }
        return mDeviceImpl.supportsOfflineProcessing(surface);
    }

    @Override
    public boolean isReprocessable() {
        return mInput != null;
@@ -500,6 +533,25 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
        }
    }

    @Override
    public void closeWithoutDraining() {
        synchronized (mDeviceImpl.mInterfaceLock) {
            if (mClosed) {
                if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
                return;
            }

            if (DEBUG) Log.v(TAG, mIdString + "close - first time");

            mClosed = true;
            mStateCallback.onClosed(this);
        }

        if (mInput != null) {
            mInput.release();
        }
    }

    @Override
    public void close() {
        synchronized (mDeviceImpl.mInterfaceLock) {
@@ -571,13 +623,13 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
    }

    /**
     * Forward callbacks from
     * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback.
     * Forward callbacks that usually originate from
     * CameraDeviceImpl.CameraDeviceCallbacks to the CameraCaptureSession.CaptureCallback.
     *
     * <p>When a capture sequence finishes, update the pending checked sequences set.</p>
     */
    @SuppressWarnings("deprecation")
    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
    private android.hardware.camera2.impl.CaptureCallback createCaptureCallbackProxy(
            Handler handler, CaptureCallback callback) {
        final Executor executor = (callback != null) ? CameraDeviceImpl.checkAndWrapHandler(
                handler) : null;
@@ -585,9 +637,9 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
        return createCaptureCallbackProxyWithExecutor(executor, callback);
    }

    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxyWithExecutor(
    private android.hardware.camera2.impl.CaptureCallback createCaptureCallbackProxyWithExecutor(
            Executor executor, CaptureCallback callback) {
        return new CameraDeviceImpl.CaptureCallback() {
        return new android.hardware.camera2.impl.CaptureCallback(executor, callback) {
            @Override
            public void onCaptureStarted(CameraDevice camera,
                    CaptureRequest request, long timestamp, long frameNumber) {
Loading