/*
* Copyright 2020 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 androidx.camera.camera2.internal;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.os.Build;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.camera.camera2.internal.SynchronizedCaptureSessionOpener.SynchronizedSessionFeature;
import androidx.camera.camera2.internal.compat.CameraCaptureSessionCompat;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
import java.util.concurrent.Executor;
/**
* The interface for accessing features in {@link CameraCaptureSession}.
*
* <p>The SynchronizedCaptureSession is similar to the {@link CameraCaptureSession}. Some device
* compatibility issues are already fixed in the SynchronizedCaptureSession.
* CameraX can access almost all the APIs in the CameraCaptureSession via the
* SynchronizedCaptureSession interface.
*
* <p>{@link SynchronizedCaptureSession} provide some extra overloaded methods that similar to the
* {@link CameraCaptureSession} APIs but doesn't need the Executor parameter input. These methods
* will automatically adopt the {@link androidx.camera.camera2.internal.annotation.CameraExecutor}
* if it need to use a Executor. Most use cases should attempt to call the overloaded method
* instead.
*
* <p>The {@link SynchronizedCaptureSessionOpener} can help to create the
* {@link SynchronizedCaptureSession} object.
*
* @see SynchronizedCaptureSessionOpener
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
interface SynchronizedCaptureSession {
@NonNull
CameraDevice getDevice();
@NonNull
StateCallback getStateCallback();
/**
* Get a {@link ListenableFuture} which indicate the progress of specific task on this
* SynchronizedCaptureSession.
*
* @param feature the key to get the ListenableFuture. The key can be
* {@link SynchronizedSessionFeature#FEATURE_WAIT_FOR_REQUEST}.
* @return the ListenableFuture which completes when the specific task is completed.
*/
@NonNull
ListenableFuture<Void> getSynchronizedBlocker(
@SynchronizedSessionFeature @NonNull String feature);
/**
* Return the {@link CameraCaptureSessionCompat} object which is used in this
* SynchronizedCaptureSession.
*/
@NonNull
CameraCaptureSessionCompat toCameraCaptureSessionCompat();
/**
* Submit a request for an image to be captured by the camera device.
*
* <p>The behavior of this method similar to the
* captureSingleRequest(CaptureRequest, Executor, CameraCaptureSession.CaptureCallback),
* except that it uses the {@link Executor} that has been set in the constructor of the
* SynchronizedCaptureSession.
*
* @param request the settings for this capture
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int captureSingleRequest(@NonNull CaptureRequest request,
@NonNull CameraCaptureSession.CaptureCallback listener) throws CameraAccessException;
/**
* Submit a list of requests to be captured in sequence as a burst. The
* burst will be captured in the minimum amount of time possible, and will
* not be interleaved with requests submitted by other capture or repeat
* calls.
*
* <p>The behavior of this method similar to the
* captureBurstRequests(List, Executor, CameraCaptureSession.CaptureCallback),
* except that it uses the {@link Executor} that has been set in the constructor of the
* SynchronizedCaptureSession.
*
* @param requests the settings for this capture
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int captureBurstRequests(
@NonNull List<CaptureRequest> requests,
@NonNull CameraCaptureSession.CaptureCallback listener)
throws CameraAccessException;
/**
* <p>Request endlessly repeating capture of a sequence of images by this capture session.</p>
*
* <p>The behavior of this method similar to the
* setSingleRepeatingRequest(CaptureRequest, Executor, CameraCaptureSession.CaptureCallback),
* except that it uses the {@link Executor} that has been set in the constructor of the
* SynchronizedCaptureSession.
*
* @param request the settings for this capture
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int setSingleRepeatingRequest(
@NonNull CaptureRequest request,
@NonNull CameraCaptureSession.CaptureCallback listener)
throws CameraAccessException;
/**
* <p>Request endlessly repeating capture of a sequence of images by this capture session.</p>
*
* <p>The behavior of this method similar to the
* setRepeatingBurstRequests(List, Executor, CameraCaptureSession.CaptureCallback),
* except that it uses the {@link Executor} that has been set in the constructor of the
* SynchronizedCaptureSession.
*
* @param requests the settings for this capture
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int setRepeatingBurstRequests(
@NonNull List<CaptureRequest> requests,
@NonNull CameraCaptureSession.CaptureCallback listener)
throws CameraAccessException;
/**
* Submit a request for an image to be captured by the camera device.
*
* <p>The behavior of this method matches that of
* CameraCaptureSessionCompat#captureSingleRequest(CaptureRequest, Executor,
* CameraCaptureSession.CaptureCallback)
*
* @param request the settings for this capture
* @param executor the executor which will be used for invoking the listener.
* @param listener The callback object to notify once this request has been processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int captureSingleRequest(@NonNull CaptureRequest request,
@NonNull /* @CallbackExecutor */ Executor executor,
@NonNull CameraCaptureSession.CaptureCallback listener) throws CameraAccessException;
/**
* Submit a list of requests to be captured in sequence as a burst. The burst will be
* captured in the minimum amount of time possible, and will not be interleaved with requests
* submitted by other capture or repeat calls.
*
* <p>The behavior of this method matches that of
* CameraCaptureSessionCompat#captureBurstRequests(List, Executor,
* CameraCaptureSession.CaptureCallback)
*
* @param requests the settings for this capture
* @param executor the executor which will be used for invoking the listener.
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int captureBurstRequests(
@NonNull List<CaptureRequest> requests,
@NonNull /* @CallbackExecutor */ Executor executor,
@NonNull CameraCaptureSession.CaptureCallback listener)
throws CameraAccessException;
/**
* <p>Request endlessly repeating capture of a sequence of images by this capture session.</p>
*
* <p>The behavior of this method matches that of
* CameraCaptureSessionCompat#setSingleRepeatingRequest(CaptureRequest, Executor,
* CameraCaptureSession.CaptureCallback)
*
* @param request the settings for this capture
* @param executor the executor which will be used for invoking the listener.
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int setSingleRepeatingRequest(
@NonNull CaptureRequest request,
@NonNull /* @CallbackExecutor */ Executor executor,
@NonNull CameraCaptureSession.CaptureCallback listener)
throws CameraAccessException;
/**
* <p>Request endlessly repeating capture of a sequence of images by this capture session.</p>
*
* <p>The behavior of this method matches that of
* CameraCaptureSessionCompat#setRepeatingBurstRequests(List, Executor,
* CameraCaptureSession.CaptureCallback)
*
* @param requests the settings for this capture
* @param executor the executor which will be used for invoking the listener.
* @param listener The callback object to notify once this request has been
* processed.
* @return int A unique capture sequence ID used by
* {@link CameraCaptureSession.CaptureCallback#onCaptureSequenceCompleted}.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
*/
int setRepeatingBurstRequests(
@NonNull List<CaptureRequest> requests,
@NonNull /* @CallbackExecutor */ Executor executor,
@NonNull CameraCaptureSession.CaptureCallback listener)
throws CameraAccessException;
void stopRepeating() throws CameraAccessException;
void abortCaptures() throws CameraAccessException;
/**
* To speed up the camera switching, the close method will close the configured session and post
* run the {@link StateCallback#onSessionFinished(SynchronizedCaptureSession)} to
* inform the SynchronizedCaptureSession is already in the closed state.
* The {@link StateCallback#onSessionFinished(SynchronizedCaptureSession)} means the session
* is changed to a closed state, any further operations on this object is not acceptable.
*/
void close();
/**
* Set the session has already been completely closed.
*
* <p>This is an internal state control method for SynchronizedSession and
* CaptureSessionRepository, so you may not need to call this method outside.
*/
void finishClose();
/**
* A callback object interface to adapting the updates from
* {@link CameraCaptureSession.StateCallback}.
*
* <p>This method is similar to the {@link CameraCaptureSession.StateCallback}. The main
* difference is users can receive the SynchronizedCaptureSession object from the callback.
*/
abstract class StateCallback {
void onReady(@NonNull SynchronizedCaptureSession session) {
}
void onActive(@NonNull SynchronizedCaptureSession session) {
}
@RequiresApi(api = Build.VERSION_CODES.O)
void onCaptureQueueEmpty(@NonNull SynchronizedCaptureSession session) {
}
@RequiresApi(api = Build.VERSION_CODES.M)
void onSurfacePrepared(@NonNull SynchronizedCaptureSession session,
@NonNull Surface surface) {
}
void onConfigured(@NonNull SynchronizedCaptureSession session) {
}
void onConfigureFailed(@NonNull SynchronizedCaptureSession session) {
}
/**
* This onClosed callback is a wrap of the CameraCaptureSession.StateCallback.onClosed, it
* will be invoked when:
* (1) CameraCaptureSession.StateCallback.onClosed is called.
* (2) The CameraDevice is disconnected. When the CameraDevice.StateCallback#onDisconnect
* is called, we will invoke this onClosed callback. Please see b/140955560.
* (3) When a new CameraCaptureSession is created, all the previous opened
* CameraCaptureSession can be treated as closed. Please see more detail in b/144817309.
*
* <p>Please note: The onClosed callback might not been called when the CameraDevice is
* closed before the CameraCaptureSession is closed.
*
* @param session the SynchronizedCaptureSession that is created by
* {@link SynchronizedCaptureSessionImpl#openCaptureSession}
*/
void onClosed(@NonNull SynchronizedCaptureSession session) {
}
/**
* This callback will be invoked in the following condition:
* (1) After the {@link SynchronizedCaptureSession#close()} is called. It means the
* SynchronizedCaptureSession is changed to a closed state. Any further operations are not
* expected for this SynchronizedCaptureSession.
* (2) When the {@link SynchronizedCaptureSession.StateCallback#onClosed} is called.
* This means the session is already detached from the camera device. For
* example, close the camera device or open a second session, which should cause the first
* one to be closed.
*
* <p>This callback only would be invoked at most one time for a configured
* SynchronizedCaptureSession. Once the callback is called, we can treat this
* SynchronizedCaptureSession is no longer active and further operations on this object
* will fail.
*
* @param session the SynchronizedCaptureSession that is created by
* {@link SynchronizedCaptureSessionImpl#openCaptureSession}
*/
void onSessionFinished(@NonNull SynchronizedCaptureSession session) {
}
}
}