Loading api/current.txt +16 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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(); core/java/android/hardware/camera2/CameraCaptureSession.java +94 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading core/java/android/hardware/camera2/CameraOfflineSession.java 0 → 100644 +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(); } core/java/android/hardware/camera2/impl/CameraCaptureSessionCore.java +10 −0 Original line number Diff line number Diff line Loading @@ -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(); } core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +62 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); Loading Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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 Loading
api/current.txt +16 −0 Original line number Diff line number Diff line Loading @@ -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; } Loading Loading @@ -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();
core/java/android/hardware/camera2/CameraCaptureSession.java +94 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading
core/java/android/hardware/camera2/CameraOfflineSession.java 0 → 100644 +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(); }
core/java/android/hardware/camera2/impl/CameraCaptureSessionCore.java +10 −0 Original line number Diff line number Diff line Loading @@ -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(); }
core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +62 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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"); Loading Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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