/*
 * Copyright (C) 2013 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.params.StreamConfigurationMap;
import android.graphics.ImageFormat;
import android.os.Handler;
import android.view.Surface;

import java.util.List;

/**
 * <p>The CameraDevice class is a representation of a single camera connected to an
 * Android device, allowing for fine-grain control of image capture and
 * post-processing at high frame rates.</p>
 *
 * <p>Your application must declare the
 * {@link android.Manifest.permission#CAMERA Camera} permission in its manifest
 * in order to access camera devices.</p>
 *
 * <p>A given camera device may provide support at one of two levels: limited or
 * full. If a device only supports the limited level, then Camera2 exposes a
 * feature set that is roughly equivalent to the older
 * {@link android.hardware.Camera Camera} API, although with a cleaner and more
 * efficient interface.  Devices that implement the full level of support
 * provide substantially improved capabilities over the older camera
 * API. Applications that target the limited level devices will run unchanged on
 * the full-level devices; if your application requires a full-level device for
 * proper operation, declare the "android.hardware.camera2.full" feature in your
 * manifest.</p>
 *
 * @see CameraManager#openCamera
 * @see android.Manifest.permission#CAMERA
 */
public abstract class CameraDevice implements AutoCloseable {

    /**
     * Create a request suitable for a camera preview window. Specifically, this
     * means that high frame rate is given priority over the highest-quality
     * post-processing. These requests would normally be used with the
     * {@link #setRepeatingRequest} method.
     *
     * @see #createCaptureRequest
     */
    public static final int TEMPLATE_PREVIEW = 1;

    /**
     * Create a request suitable for still image capture. Specifically, this
     * means prioritizing image quality over frame rate. These requests would
     * commonly be used with the {@link #capture} method.
     *
     * @see #createCaptureRequest
     */
    public static final int TEMPLATE_STILL_CAPTURE = 2;

    /**
     * Create a request suitable for video recording. Specifically, this means
     * that a stable frame rate is used, and post-processing is set for
     * recording quality. These requests would commonly be used with the
     * {@link #setRepeatingRequest} method.
     *
     * @see #createCaptureRequest
     */
    public static final int TEMPLATE_RECORD  = 3;

    /**
     * Create a request suitable for still image capture while recording
     * video. Specifically, this means maximizing image quality without
     * disrupting the ongoing recording. These requests would commonly be used
     * with the {@link #capture} method while a request based on
     * {@link #TEMPLATE_RECORD} is is in use with {@link #setRepeatingRequest}.
     *
     * @see #createCaptureRequest
     */
    public static final int TEMPLATE_VIDEO_SNAPSHOT = 4;

    /**
     * Create a request suitable for zero shutter lag still capture. This means
     * means maximizing image quality without compromising preview frame rate.
     * AE/AWB/AF should be on auto mode.
     *
     * @see #createCaptureRequest
     */
    public static final int TEMPLATE_ZERO_SHUTTER_LAG = 5;

    /**
     * A basic template for direct application control of capture
     * parameters. All automatic control is disabled (auto-exposure, auto-white
     * balance, auto-focus), and post-processing parameters are set to preview
     * quality. The manual capture parameters (exposure, sensitivity, and so on)
     * are set to reasonable defaults, but should be overriden by the
     * application depending on the intended use case.
     *
     * @see #createCaptureRequest
     */
    public static final int TEMPLATE_MANUAL = 6;

    /**
     * Get the ID of this camera device.
     *
     * <p>This matches the ID given to {@link CameraManager#openCamera} to instantiate this
     * this camera device.</p>
     *
     * <p>This ID can be used to query the camera device's {@link
     * CameraCharacteristics fixed properties} with {@link
     * CameraManager#getCameraCharacteristics}.</p>
     *
     * <p>This method can be called even if the device has been closed or has encountered
     * a serious error.</p>
     *
     * @return the ID for this camera device
     *
     * @see CameraManager#getCameraCharacteristics
     * @see CameraManager#getCameraIdList
     */
    public abstract String getId();

    /**
     * <p>Set up a new output set of Surfaces for the camera device.</p>
     *
     * <p>The configuration determines the set of potential output Surfaces for
     * the camera device for each capture request. A given request may use all
     * or a only some of the outputs. This method must be called before requests
     * can be submitted to the camera with {@link #capture capture},
     * {@link #captureBurst captureBurst},
     * {@link #setRepeatingRequest setRepeatingRequest}, or
     * {@link #setRepeatingBurst setRepeatingBurst}.</p>
     *
     * <p>Surfaces suitable for inclusion as a camera output can be created for
     * various use cases and targets:</p>
     *
     * <ul>
     *
     * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Set
     *   the size of the Surface with
     *   {@link android.view.SurfaceHolder#setFixedSize} to be one of the
     *   supported
     *   {@link StreamConfigurationMap#getOutputSizes(Class) processed sizes}
     *   before calling {@link android.view.SurfaceHolder#getSurface}.</li>
     *
     * <li>For accessing through an OpenGL texture via a
     *   {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of
     *   the SurfaceTexture with
     *   {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
     *   of the supported
     *   {@link StreamConfigurationMap#getOutputSizes(Class) processed sizes}
     *   before creating a Surface from the SurfaceTexture with
     *   {@link Surface#Surface}.</li>
     *
     * <li>For recording with {@link android.media.MediaCodec}: Call
     *   {@link android.media.MediaCodec#createInputSurface} after configuring
     *   the media codec to use one of the
     *   {@link StreamConfigurationMap#getOutputSizes(Class) processed sizes}
     *   </li>
     *
     * <li>For recording with {@link android.media.MediaRecorder}: TODO</li>
     *
     * <li>For efficient YUV processing with {@link android.renderscript}:
     *   Create a RenderScript
     *   {@link android.renderscript.Allocation Allocation} with a supported YUV
     *   type, the IO_INPUT flag, and one of the supported
     *   {@link StreamConfigurationMap#getOutputSizes(int) processed sizes}. Then
     *   obtain the Surface with
     *   {@link android.renderscript.Allocation#getSurface}.</li>
     *
     * <li>For access to uncompressed or {@link ImageFormat#JPEG JPEG} data in the application:
     * Create a {@link android.media.ImageReader} object with the desired
     * {@link StreamConfigurationMap#getOutputFormats() image format}, and a size from the matching
     * {@link StreamConfigurationMap#getOutputSizes(int) processed size} and {@code format}.
     * Then obtain a {@link Surface} from it.</li>
     * </ul>
     *
     * </p>
     *
     * <p>This function can take several hundred milliseconds to execute, since
     * camera hardware may need to be powered on or reconfigured.</p>
     *
     * <p>The camera device will query each Surface's size and formats upon this
     * call, so they must be set to a valid setting at this time (in particular:
     * if the format is user-visible, it must be one of
     * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
     * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
     *
     * <p>When this method is called with valid Surfaces, the device will transition to the {@link
     * StateListener#onBusy busy state}. Once configuration is complete, the device will transition
     * into the {@link StateListener#onIdle idle state}. Capture requests using the newly-configured
     * Surfaces may then be submitted with {@link #capture}, {@link #captureBurst}, {@link
     * #setRepeatingRequest}, or {@link #setRepeatingBurst}.</p>
     *
     * <p>If this method is called while the camera device is still actively processing previously
     * submitted captures, then the following sequence of events occurs: The device transitions to
     * the busy state and calls the {@link StateListener#onBusy} callback. Second, if a repeating
     * request is set it is cleared.  Third, the device finishes up all in-flight and pending
     * requests. Finally, once the device is idle, it then reconfigures its outputs, and calls the
     * {@link StateListener#onIdle} method once it is again ready to accept capture
     * requests. Therefore, no submitted work is discarded. To idle as fast as possible, use {@link
     * #flush} and wait for the idle callback before calling configureOutputs. This will discard
     * work, but reaches the new configuration sooner.</p>
     *
     * <p>Using larger resolution outputs, or more outputs, can result in slower
     * output rate from the device.</p>
     *
     * <p>Configuring the outputs with an empty or null list will transition the camera into an
     * {@link StateListener#onUnconfigured unconfigured state} instead of the {@link
     * StateListener#onIdle idle state}.  </p>
     *
     * <p>Calling configureOutputs with the same arguments as the last call to
     * configureOutputs has no effect, and the {@link StateListener#onBusy busy}
     * and {@link StateListener#onIdle idle} state transitions will happen
     * immediately.</p>
     *
     * @param outputs The new set of Surfaces that should be made available as
     * targets for captured image data.
     *
     * @throws IllegalArgumentException if the set of output Surfaces do not
     * meet the requirements
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera device is not idle, or
     *                               if the camera device has been closed
     *
     * @see StateListener#onBusy
     * @see StateListener#onIdle
     * @see StateListener#onActive
     * @see StateListener#onUnconfigured
     * @see #stopRepeating
     * @see #flush
     * @see StreamConfigurationMap#getOutputFormats()
     * @see StreamConfigurationMap#getOutputSizes(int)
     * @see StreamConfigurationMap#getOutputSizes(Class)
     * @deprecated Use {@link #createCaptureSession} instead
     */
    @Deprecated
    public abstract void configureOutputs(List<Surface> outputs) throws CameraAccessException;

    /**
     * <p>Create a new camera capture session by providing the target output set of Surfaces to the
     * camera device.</p>
     *
     * <p>The active capture session determines the set of potential output Surfaces for
     * the camera device for each capture request. A given request may use all
     * or a only some of the outputs. Once the CameraCaptureSession is created, requests can be
     * can be submitted with {@link CameraCaptureSession#capture capture},
     * {@link CameraCaptureSession#captureBurst captureBurst},
     * {@link CameraCaptureSession#setRepeatingRequest setRepeatingRequest}, or
     * {@link CameraCaptureSession#setRepeatingBurst setRepeatingBurst}.</p>
     *
     * <p>Surfaces suitable for inclusion as a camera output can be created for
     * various use cases and targets:</p>
     *
     * <ul>
     *
     * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Set the size of the
     *   Surface with {@link android.view.SurfaceHolder#setFixedSize} to be one of the sizes
     *   returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(SurfaceView.class)}
     *   and then obtain the Surface by calling {@link android.view.SurfaceHolder#getSurface}.</li>
     *
     * <li>For accessing through an OpenGL texture via a
     *   {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of
     *   the SurfaceTexture with
     *   {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
     *   of the sizes returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(SurfaceTexture.class)}
     *   before creating a Surface from the SurfaceTexture with
     *   {@link Surface#Surface}.</li>
     *
     * <li>For recording with {@link android.media.MediaCodec}: Call
     *   {@link android.media.MediaCodec#createInputSurface} after configuring
     *   the media codec to use one of the sizes returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(MediaCodec.class)}
     *   </li>
     *
     * <li>For recording with {@link android.media.MediaRecorder}: Call
     *   {@link android.media.MediaRecorder#getSurface} after configuring the media recorder to use
     *   one of the sizes returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(MediaRecorder.class)},
     *   or configuring it to use one of the supported
     *   {@link android.media.CamcorderProfile CamcorderProfiles}.</li>
     *
     * <li>For efficient YUV processing with {@link android.renderscript}:
     *   Create a RenderScript
     *   {@link android.renderscript.Allocation Allocation} with a supported YUV
     *   type, the IO_INPUT flag, and one of the sizes returned by
     *   {@link StreamConfigurationMap#getOutputSizes(Class) getOutputSizes(Allocation.class)},
     *   Then obtain the Surface with
     *   {@link android.renderscript.Allocation#getSurface}.</li>
     *
     * <li>For access to raw, uncompressed or JPEG data in the application: Create a
     *   {@link android.media.ImageReader} object with the one of the supported
     *   {@link StreamConfigurationMap#getOutputFormats() output image formats}, and a
     *   size from the supported
     *   {@link StreamConfigurationMap#getOutputSizes(int) sizes for that format}. Then obtain
     *   a Surface from it with {@link android.media.ImageReader#getSurface}.</li>
     *
     * </ul>
     *
     * </p>
     *
     * <p>The camera device will query each Surface's size and formats upon this
     * call, so they must be set to a valid setting at this time (in particular:
     * if the format is user-visible, it must be one of
     * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
     * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
     *
     * <p>It can take several hundred milliseconds for the session's configuration to complete,
     * since camera hardware may need to be powered on or reconfigured. Once the configuration is
     * complete and the session is ready to actually capture data, the provided
     * {@link CameraCaptureSession.StateListener}'s
     * {@link CameraCaptureSession.StateListener#onConfigured} callback will be called.</p>
     *
     * <p>If a prior CameraCaptureSession already exists when a new one is created, the previous
     * session is closed. Any in-progress capture requests made on the prior session will be
     * completed before the new session is configured and is able to start capturing its own
     * requests. To minimize the transition time, the {@link CameraCaptureSession#abortCaptures}
     * call can be used to discard the remaining requests for the prior capture session before a new
     * one is created. Note that once the new session is created, the old one can no longer have its
     * captures aborted.</p>
     *
     * <p>Using larger resolution outputs, or more outputs, can result in slower
     * output rate from the device.</p>
     *
     * <p>Configuring a session with an empty or null list will close the current session, if
     * any. This can be used to release the current session's target surfaces for another use.</p>
     *
     * @param outputs The new set of Surfaces that should be made available as
     *                targets for captured image data.
     * @param listener The listener to notify about the status of the new capture session.
     * @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}.
     * <!--
     * @return A new camera capture session to use, or null if an empty/null set of Surfaces is
     *         provided.
     * -->
     * @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements,
     *                                  the listener is null, or the handler is null but the current
     *                                  thread has no looper.
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera device has been closed
     *
     * @see CameraCaptureSession
     * @see StreamConfigurationMap#getOutputFormats()
     * @see StreamConfigurationMap#getOutputSizes(int)
     * @see StreamConfigurationMap#getOutputSizes(Class)
     */
    public abstract void createCaptureSession(List<Surface> outputs,
            CameraCaptureSession.StateListener listener, Handler handler)
            throws CameraAccessException;

    /**
     * <p>Create a {@link CaptureRequest.Builder} for new capture requests,
     * initialized with template for a target use case. The settings are chosen
     * to be the best options for the specific camera device, so it is not
     * recommended to reuse the same request for a different camera device;
     * create a builder specific for that device and template and override the
     * settings as desired, instead.</p>
     *
     * @param templateType An enumeration selecting the use case for this
     * request; one of the CameraDevice.TEMPLATE_ values.
     * @return a builder for a capture request, initialized with default
     * settings for that template, and no output streams
     *
     * @throws IllegalArgumentException if the templateType is not in the list
     * of supported templates.
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera device has been closed
     *
     * @see #TEMPLATE_PREVIEW
     * @see #TEMPLATE_RECORD
     * @see #TEMPLATE_STILL_CAPTURE
     * @see #TEMPLATE_VIDEO_SNAPSHOT
     * @see #TEMPLATE_MANUAL
     */
    public abstract CaptureRequest.Builder createCaptureRequest(int templateType)
            throws CameraAccessException;

    /**
     * <p>Submit a request for an image to be captured by this CameraDevice.</p>
     *
     * <p>The request defines all the parameters for capturing the single image,
     * including sensor, lens, flash, and post-processing settings.</p>
     *
     * <p>Each request will produce one {@link CaptureResult} and produce new
     * frames for one or more target Surfaces, set with the CaptureRequest
     * builder's {@link CaptureRequest.Builder#addTarget} method. The target
     * surfaces must be configured as active outputs with
     * {@link #configureOutputs} before calling this method.</p>
     *
     * <p>Multiple requests can be in progress at once. They are processed in
     * first-in, first-out order, with minimal delays between each
     * capture. Requests submitted through this method have higher priority than
     * those submitted through {@link #setRepeatingRequest} or
     * {@link #setRepeatingBurst}, and will be processed as soon as the current
     * repeat/repeatBurst processing completes.</p>
     *
     * @param request the settings for this capture
     * @param listener The callback object to notify once this request has been
     * processed. If null, no metadata will be produced for this capture,
     * although image data will still be produced.
     * @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}.
     *
     * @return int A unique capture sequence ID used by
     *             {@link CaptureListener#onCaptureSequenceCompleted}.
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera is currently busy or unconfigured,
     *                               or the camera device has been closed.
     * @throws IllegalArgumentException If the request targets Surfaces not
     * currently configured as outputs. Or if the handler is null, the listener
     * is not null, and the calling thread has no looper.
     *
     * @see #captureBurst
     * @see #setRepeatingRequest
     * @see #setRepeatingBurst
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler)
            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 requests will be captured in order, each capture producing one
     * {@link CaptureResult} and image buffers for one or more target
     * {@link android.view.Surface surfaces}. The target surfaces for each
     * request (set with {@link CaptureRequest.Builder#addTarget}) must be
     * configured as active outputs with {@link #configureOutputs} before
     * calling this method.</p>
     *
     * <p>The main difference between this method and simply calling
     * {@link #capture} repeatedly is that this method guarantees that no
     * other requests will be interspersed with the burst.</p>
     *
     * @param requests the list of settings for this burst capture
     * @param listener The callback object to notify each time one of the
     * requests in the burst has been processed. If null, no metadata will be
     * produced for any requests in this burst, although image data will still
     * be produced.
     * @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}.
     *
     * @return int A unique capture sequence ID used by
     *             {@link CaptureListener#onCaptureSequenceCompleted}.
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera is currently busy or unconfigured,
     *                               or the camera device has been closed.
     * @throws IllegalArgumentException If the requests target Surfaces not
     * currently configured as outputs. Or if the handler is null, the listener
     * is not null, and the calling thread has no looper. Or if no requests were
     * passed in.
     *
     * @see #capture
     * @see #setRepeatingRequest
     * @see #setRepeatingBurst
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
            Handler handler) throws CameraAccessException;

    /**
     * Request endlessly repeating capture of images by this CameraDevice.
     *
     * <p>With this method, the CameraDevice will continually capture images
     * using the settings in the provided {@link CaptureRequest}, at the maximum
     * rate possible.</p>
     *
     * <p>Repeating requests are a simple way for an application to maintain a
     * preview or other continuous stream of frames, without having to
     * continually submit identical requests through {@link #capture}.</p>
     *
     * <p>Repeat requests have lower priority than those submitted
     * through {@link #capture} or {@link #captureBurst}, so if
     * {@link #capture} is called when a repeating request is active, the
     * capture request will be processed before any further repeating
     * requests are processed.<p>
     *
     * <p>Repeating requests are a simple way for an application to maintain a
     * preview or other continuous stream of frames, without having to submit
     * requests through {@link #capture} at video rates.</p>
     *
     * <p>To stop the repeating capture, call {@link #stopRepeating}. Calling
     * {@link #flush} will also clear the request.</p>
     *
     * <p>Calling this method will replace any earlier repeating request or
     * burst set up by this method or {@link #setRepeatingBurst}, although any
     * in-progress burst will be completed before the new repeat request will be
     * used.</p>
     *
     * @param request the request to repeat indefinitely
     * @param listener The callback object to notify every time the
     * request finishes processing. If null, no metadata will be
     * produced for this stream of requests, although image data will
     * still be produced.
     * @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}.
     *
     * @return int A unique capture sequence ID used by
     *             {@link CaptureListener#onCaptureSequenceCompleted}.
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera is currently busy or unconfigured,
     *                               or the camera device has been closed.
     * @throws IllegalArgumentException If the requests reference Surfaces not
     * currently configured as outputs. Or if the handler is null, the listener
     * is not null, and the calling thread has no looper.
     *
     * @see #capture
     * @see #captureBurst
     * @see #setRepeatingBurst
     * @see #stopRepeating
     * @see #flush
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public abstract int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
            Handler handler) throws CameraAccessException;

    /**
     * <p>Request endlessly repeating capture of a sequence of images by this
     * CameraDevice.</p>
     *
     * <p>With this method, the CameraDevice will continually capture images,
     * cycling through the settings in the provided list of
     * {@link CaptureRequest CaptureRequests}, at the maximum rate possible.</p>
     *
     * <p>If a request is submitted through {@link #capture} or
     * {@link #captureBurst}, the current repetition of the request list will be
     * completed before the higher-priority request is handled. This guarantees
     * that the application always receives a complete repeat burst captured in
     * minimal time, instead of bursts interleaved with higher-priority
     * captures, or incomplete captures.</p>
     *
     * <p>Repeating burst requests are a simple way for an application to
     * maintain a preview or other continuous stream of frames where each
     * request is different in a predicatable way, without having to continually
     * submit requests through {@link #captureBurst} .</p>
     *
     * <p>To stop the repeating capture, call {@link #stopRepeating}. Any
     * ongoing burst will still be completed, however. Calling
     * {@link #flush} will also clear the request.</p>
     *
     * <p>Calling this method will replace a previously-set repeating request or
     * burst set up by this method or {@link #setRepeatingRequest}, although any
     * in-progress burst will be completed before the new repeat burst will be
     * used.</p>
     *
     * @param requests the list of requests to cycle through indefinitely
     * @param listener The callback object to notify each time one of the
     * requests in the repeating bursts has finished processing. If null, no
     * metadata will be produced for this stream of requests, although image
     * data will still be produced.
     * @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}.
     *
     * @return int A unique capture sequence ID used by
     *             {@link CaptureListener#onCaptureSequenceCompleted}.
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera is currently busy or unconfigured,
     *                               or the camera device has been closed.
     * @throws IllegalArgumentException If the requests reference Surfaces not
     * currently configured as outputs. Or if the handler is null, the listener
     * is not null, and the calling thread has no looper. Or if no requests were
     * passed in.
     *
     * @see #capture
     * @see #captureBurst
     * @see #setRepeatingRequest
     * @see #stopRepeating
     * @see #flush
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
            Handler handler) throws CameraAccessException;

    /**
     * <p>Cancel any ongoing repeating capture set by either
     * {@link #setRepeatingRequest setRepeatingRequest} or
     * {@link #setRepeatingBurst}. Has no effect on requests submitted through
     * {@link #capture capture} or {@link #captureBurst captureBurst}.</p>
     *
     * <p>Any currently in-flight captures will still complete, as will any
     * burst that is mid-capture. To ensure that the device has finished
     * processing all of its capture requests and is in idle state, wait for the
     * {@link StateListener#onIdle} callback after calling this
     * method..</p>
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera is currently busy or unconfigured,
     *                               or the camera device has been closed.
     *
     * @see #setRepeatingRequest
     * @see #setRepeatingBurst
     * @see StateListener#onIdle
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public abstract void stopRepeating() throws CameraAccessException;

    /**
     * Flush all captures currently pending and in-progress as fast as
     * possible.
     *
     * <p>The camera device will discard all of its current work as fast as
     * possible. Some in-flight captures may complete successfully and call
     * {@link CaptureListener#onCaptureCompleted}, while others will trigger
     * their {@link CaptureListener#onCaptureFailed} callbacks. If a repeating
     * request or a repeating burst is set, it will be cleared by the flush.</p>
     *
     * <p>This method is the fastest way to idle the camera device for
     * reconfiguration with {@link #configureOutputs}, at the cost of discarding
     * in-progress work. Once the flush is complete, the idle callback will be
     * called.</p>
     *
     * <p>Flushing will introduce at least a brief pause in the stream of data
     * from the camera device, since once the flush is complete, the first new
     * request has to make it through the entire camera pipeline before new
     * output buffers are produced.</p>
     *
     * <p>This means that using {@code flush()} to simply remove pending
     * requests is not recommended; it's best used for quickly switching output
     * configurations, or for cancelling long in-progress requests (such as a
     * multi-second capture).</p>
     *
     * @throws CameraAccessException if the camera device is no longer connected or has
     *                               encountered a fatal error
     * @throws IllegalStateException if the camera is not idle/active,
     *                               or the camera device has been closed.
     *
     * @see #setRepeatingRequest
     * @see #setRepeatingBurst
     * @see #configureOutputs
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public abstract void flush() throws CameraAccessException;

    /**
     * Close the connection to this camera device as quickly as possible.
     *
     * <p>Immediately after this call, all calls to the camera device or active session interface
     * will throw a {@link IllegalStateException}, except for calls to close(). Once the device has
     * fully shut down, the {@link StateListener#onClosed} callback will be called, and the camera
     * is free to be re-opened.</p>
     *
     * <p>Immediately after this call, besides the final {@link StateListener#onClosed} calls, no
     * further callbacks from the device or the active session will occur, and any remaining
     * submitted capture requests will be discarded, as if
     * {@link CameraCaptureSession#abortCaptures} had been called, except that no success or failure
     * callbacks will be invoked.</p>
     *
     */
    @Override
    public abstract void close();

    /**
     * <p>A listener for tracking the progress of a {@link CaptureRequest}
     * submitted to the camera device.</p>
     *
     * <p>This listener is called when a request triggers a capture to start,
     * and when the capture is complete. In case on an error capturing an image,
     * the error method is triggered instead of the completion method.</p>
     *
     * @see #capture
     * @see #captureBurst
     * @see #setRepeatingRequest
     * @see #setRepeatingBurst
     * @deprecated Use {@link CameraCaptureSession} instead
     */
    @Deprecated
    public static abstract class CaptureListener {

        /**
         * This constant is used to indicate that no images were captured for
         * the request.
         *
         * @hide
         */
        public static final int NO_FRAMES_CAPTURED = -1;

        /**
         * This method is called when the camera device has started capturing
         * the output image for the request, at the beginning of image exposure.
         *
         * <p>This callback is invoked right as the capture of a frame begins,
         * so it is the most appropriate time for playing a shutter sound,
         * or triggering UI indicators of capture.</p>
         *
         * <p>The request that is being used for this capture is provided, along
         * with the actual timestamp for the start of exposure. This timestamp
         * matches the timestamp that will be included in
         * {@link CaptureResult#SENSOR_TIMESTAMP the result timestamp field},
         * and in the buffers sent to each output Surface. These buffer
         * timestamps are accessible through, for example,
         * {@link android.media.Image#getTimestamp() Image.getTimestamp()} or
         * {@link android.graphics.SurfaceTexture#getTimestamp()}.</p>
         *
         * <p>For the simplest way to play a shutter sound camera shutter or a
         * video recording start/stop sound, see the
         * {@link android.media.MediaActionSound} class.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the CameraDevice sending the callback
         * @param request the request for the capture that just begun
         * @param timestamp the timestamp at start of capture, in nanoseconds.
         *
         * @see android.media.MediaActionSound
         */
        public void onCaptureStarted(CameraDevice camera,
                CaptureRequest request, long timestamp) {
            // default empty implementation
        }

        /**
         * This method is called when some results from an image capture are
         * available.
         *
         * <p>The result provided here will contain some subset of the fields of
         * a full result. Multiple onCapturePartial calls may happen per
         * capture; a given result field will only be present in one partial
         * capture at most. The final onCaptureCompleted call will always
         * contain all the fields, whether onCapturePartial was called or
         * not.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera The CameraDevice sending the callback.
         * @param request The request that was given to the CameraDevice
         * @param result The partial output metadata from the capture, which
         * includes a subset of the CaptureResult fields.
         *
         * @see #capture
         * @see #captureBurst
         * @see #setRepeatingRequest
         * @see #setRepeatingBurst
         *
         * @hide
         */
        public void onCapturePartial(CameraDevice camera,
                CaptureRequest request, CaptureResult result) {
            // default empty implementation
        }

        /**
         * This method is called when an image capture makes partial forward progress; some
         * (but not all) results from an image capture are available.
         *
         * <p>The result provided here will contain some subset of the fields of
         * a full result. Multiple {@link #onCaptureProgressed} calls may happen per
         * capture; a given result field will only be present in one partial
         * capture at most. The final {@link #onCaptureCompleted} call will always
         * contain all the fields (in particular, the union of all the fields of all
         * the partial results composing the total result).</p>
         *
         * <p>For each request, some result data might be available earlier than others. The typical
         * delay between each partial result (per request) is a single frame interval.
         * For performance-oriented use-cases, applications should query the metadata they need
         * to make forward progress from the partial results and avoid waiting for the completed
         * result.</p>
         *
         * <p>Each request will generate at least {@code 1} partial results, and at most
         * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT} partial results.</p>
         *
         * <p>Depending on the request settings, the number of partial results per request
         * will vary, although typically the partial count could be the same as long as the
         * camera device subsystems enabled stay the same.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera The CameraDevice sending the callback.
         * @param request The request that was given to the CameraDevice
         * @param partialResult The partial output metadata from the capture, which
         * includes a subset of the {@link TotalCaptureResult} fields.
         *
         * @see #capture
         * @see #captureBurst
         * @see #setRepeatingRequest
         * @see #setRepeatingBurst
         */
        public void onCaptureProgressed(CameraDevice camera,
                CaptureRequest request, CaptureResult partialResult) {
            // default empty implementation
        }

        /**
         * This method is called when an image capture has fully completed and all the
         * result metadata is available.
         *
         * <p>This callback will always fire after the last {@link #onCaptureProgressed};
         * in other words, no more partial results will be delivered once the completed result
         * is available.</p>
         *
         * <p>For performance-intensive use-cases where latency is a factor, consider
         * using {@link #onCaptureProgressed} instead.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera The CameraDevice sending the callback.
         * @param request The request that was given to the CameraDevice
         * @param result The total output metadata from the capture, including the
         * final capture parameters and the state of the camera system during
         * capture.
         *
         * @see #capture
         * @see #captureBurst
         * @see #setRepeatingRequest
         * @see #setRepeatingBurst
         */
        public void onCaptureCompleted(CameraDevice camera,
                CaptureRequest request, TotalCaptureResult result) {
            // default empty implementation
        }

        /**
         * This method is called instead of {@link #onCaptureCompleted} when the
         * camera device failed to produce a {@link CaptureResult} for the
         * request.
         *
         * <p>Other requests are unaffected, and some or all image buffers from
         * the capture may have been pushed to their respective output
         * streams.</p>
         *
         * <p>Some partial results may have been delivered before the capture fails;
         * however after this callback fires, no more partial results will be delivered by
         * {@link #onCaptureProgressed}.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera
         *            The CameraDevice sending the callback.
         * @param request
         *            The request that was given to the CameraDevice
         * @param failure
         *            The output failure from the capture, including the failure reason
         *            and the frame number.
         *
         * @see #capture
         * @see #captureBurst
         * @see #setRepeatingRequest
         * @see #setRepeatingBurst
         */
        public void onCaptureFailed(CameraDevice camera,
                CaptureRequest request, CaptureFailure failure) {
            // default empty implementation
        }

        /**
         * This method is called independently of the others in CaptureListener,
         * when a capture sequence finishes and all {@link CaptureResult}
         * or {@link CaptureFailure} for it have been returned via this listener.
         *
         * <p>In total, there will be at least one result/failure returned by this listener
         * before this callback is invoked. If the capture sequence is aborted before any
         * requests have been processed, {@link #onCaptureSequenceAborted} is invoked instead.</p>
         *
         * <p>The default implementation does nothing.</p>
         *
         * @param camera
         *            The CameraDevice sending the callback.
         * @param sequenceId
         *            A sequence ID returned by the {@link #capture} family of functions.
         * @param frameNumber
         *            The last frame number (returned by {@link CaptureResult#getFrameNumber}
         *            or {@link CaptureFailure#getFrameNumber}) in the capture sequence.
         *
         * @see CaptureResult#getFrameNumber()
         * @see CaptureFailure#getFrameNumber()
         * @see CaptureResult#getSequenceId()
         * @see CaptureFailure#getSequenceId()
         * @see #onCaptureSequenceAborted
         */
        public void onCaptureSequenceCompleted(CameraDevice camera,
                int sequenceId, long frameNumber) {
            // default empty implementation
        }

        /**
         * This method is called independently of the others in CaptureListener,
         * when a capture sequence aborts before any {@link CaptureResult}
         * or {@link CaptureFailure} for it have been returned via this listener.
         *
         * <p>Due to the asynchronous nature of the camera device, not all submitted captures
         * are immediately processed. It is possible to clear out the pending requests
         * by a variety of operations such as {@link CameraDevice#stopRepeating} or
         * {@link CameraDevice#flush}. When such an event happens,
         * {@link #onCaptureSequenceCompleted} will not be called.</p>
         *
         * <p>The default implementation does nothing.</p>
         *
         * @param camera
         *            The CameraDevice sending the callback.
         * @param sequenceId
         *            A sequence ID returned by the {@link #capture} family of functions.
         *
         * @see CaptureResult#getFrameNumber()
         * @see CaptureFailure#getFrameNumber()
         * @see CaptureResult#getSequenceId()
         * @see CaptureFailure#getSequenceId()
         * @see #onCaptureSequenceCompleted
         */
        public void onCaptureSequenceAborted(CameraDevice camera,
                int sequenceId) {
            // default empty implementation
        }
    }

    /**
     * A listener for notifications about the state of a camera
     * device.
     *
     * <p>A listener must be provided to the {@link CameraManager#openCamera}
     * method to open a camera device.</p>
     *
     * <p>These events include notifications about the device becoming idle (
     * allowing for {@link #configureOutputs} to be called), about device
     * disconnection, and about unexpected device errors.</p>
     *
     * <p>Events about the progress of specific {@link CaptureRequest
     * CaptureRequests} are provided through a {@link CaptureListener} given to
     * the {@link #capture}, {@link #captureBurst}, {@link
     * #setRepeatingRequest}, or {@link #setRepeatingBurst} methods.
     *
     * @see CameraManager#openCamera
     */
    public static abstract class StateListener {
       /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device is in use already.
         *
         * <p>
         * This error can be produced when opening the camera fails.
         * </p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_IN_USE = 1;

        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device could not be opened
         * because there are too many other open camera devices.
         *
         * <p>
         * The system-wide limit for number of open cameras has been reached,
         * and more camera devices cannot be opened until previous instances are
         * closed.
         * </p>
         *
         * <p>
         * This error can be produced when opening the camera fails.
         * </p>
         *
         * @see #onError
         */
        public static final int ERROR_MAX_CAMERAS_IN_USE = 2;

        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device could not be opened due to a device
         * policy.
         *
         * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
         * @see #onError
         */
        public static final int ERROR_CAMERA_DISABLED = 3;

       /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera device has encountered a fatal error.
         *
         * <p>The camera device needs to be re-opened to be used again.</p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_DEVICE = 4;

        /**
         * An error code that can be reported by {@link #onError}
         * indicating that the camera service has encountered a fatal error.
         *
         * <p>The Android device may need to be shut down and restarted to restore
         * camera function, or there may be a persistent hardware problem.</p>
         *
         * <p>An attempt at recovery <i>may</i> be possible by closing the
         * CameraDevice and the CameraManager, and trying to acquire all resources
         * again from scratch.</p>
         *
         * @see #onError
         */
        public static final int ERROR_CAMERA_SERVICE = 5;

        /**
         * The method called when a camera device has finished opening.
         *
         * <p>An opened camera will immediately afterwards transition into
         * {@link #onUnconfigured}.</p>
         *
         * @param camera the camera device that has become opened
         */
        public abstract void onOpened(CameraDevice camera); // Must implement

        /**
         * The method called when a camera device has no outputs configured.
         *
         * <p>An unconfigured camera device needs to be configured with
         * {@link CameraDevice#configureOutputs} before being able to
         * submit any capture request.</p>
         *
         * <p>This state may be entered by a newly opened camera or by
         * calling {@link CameraDevice#configureOutputs} with a null/empty
         * list of Surfaces when idle.</p>
         *
         * <p>Any attempts to submit a capture request while in this state
         * will result in an {@link IllegalStateException} being thrown.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device has that become unconfigured
         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
         */
        @Deprecated
        public void onUnconfigured(CameraDevice camera) {
            // Default empty implementation
        }

        /**
         * The method called when a camera device begins processing
         * {@link CaptureRequest capture requests}.
         *
         * <p>A camera may not be re-configured while in this state. The camera
         * will transition to the idle state once all pending captures have
         * completed. If a repeating request is set, the camera will remain active
         * until it is cleared and the remaining requests finish processing. To
         * transition to the idle state as quickly as possible, call {@link #flush()},
         * which will idle the camera device as quickly as possible, likely canceling
         * most in-progress captures.</p>
         *
         * <p>All calls except for {@link CameraDevice#configureOutputs} are
         * legal while in this state.
         * </p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device that has become active
         *
         * @see CameraDevice#capture
         * @see CameraDevice#captureBurst
         * @see CameraDevice#setRepeatingBurst
         * @see CameraDevice#setRepeatingRequest
         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
         */
        @Deprecated
        public void onActive(CameraDevice camera) {
            // Default empty implementation
        }

        /**
         * The method called when a camera device is busy.
         *
         * <p>A camera becomes busy while it's outputs are being configured
         * (after a call to {@link CameraDevice#configureOutputs} or while it's
         * being flushed (after a call to {@link CameraDevice#flush}.</p>
         *
         * <p>Once the on-going operations are complete, the camera will automatically
         * transition into {@link #onIdle} if there is at least one configured output,
         * or {@link #onUnconfigured} otherwise.</p>
         *
         * <p>Any attempts to manipulate the camera while its is busy
         * will result in an {@link IllegalStateException} being thrown.</p>
         *
         * <p>Only the following methods are valid to call while in this state:
         * <ul>
         * <li>{@link CameraDevice#getId}</li>
         * <li>{@link CameraDevice#createCaptureRequest}</li>
         * <li>{@link CameraDevice#close}</li>
         * </ul>
         * </p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device that has become busy
         *
         * @see CameraDevice#configureOutputs
         * @see CameraDevice#flush
         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
         */
        @Deprecated
        public void onBusy(CameraDevice camera) {
            // Default empty implementation
        }

        /**
         * The method called when a camera device has been closed with
         * {@link CameraDevice#close}.
         *
         * <p>Any attempt to call methods on this CameraDevice in the
         * future will throw a {@link IllegalStateException}.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device that has become closed
         */
        public void onClosed(CameraDevice camera) {
            // Default empty implementation
        }

        /**
         * The method called when a camera device has finished processing all
         * submitted capture requests and has reached an idle state.
         *
         * <p>An idle camera device can have its outputs changed by calling {@link
         * CameraDevice#configureOutputs}, which will transition it into the busy state.</p>
         *
         * <p>To idle and reconfigure outputs without canceling any submitted
         * capture requests, the application needs to clear its repeating
         * request/burst, if set, with {@link CameraDevice#stopRepeating}, and
         * then wait for this callback to be called before calling {@link
         * CameraDevice#configureOutputs}.</p>
         *
         * <p>To idle and reconfigure a camera device as fast as possible, the
         * {@link CameraDevice#flush} method can be used, which will discard all
         * pending and in-progress capture requests. Once the {@link
         * CameraDevice#flush} method is called, the application must wait for
         * this callback to fire before calling {@link
         * CameraDevice#configureOutputs}.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param camera the camera device that has become idle
         *
         * @see CameraDevice#configureOutputs
         * @see CameraDevice#stopRepeating
         * @see CameraDevice#flush
         * @deprecated Use {@link CameraCaptureSession.StateListener} instead.
         */
        @Deprecated
        public void onIdle(CameraDevice camera) {
            // Default empty implementation
        }

        /**
         * The method called when a camera device is no longer available for
         * use.
         *
         * <p>This callback may be called instead of {@link #onOpened}
         * if opening the camera fails.</p>
         *
         * <p>Any attempt to call methods on this CameraDevice will throw a
         * {@link CameraAccessException}. The disconnection could be due to a
         * change in security policy or permissions; the physical disconnection
         * of a removable camera device; or the camera being needed for a
         * higher-priority use case.</p>
         *
         * <p>There may still be capture listener callbacks that are called
         * after this method is called, or new image buffers that are delivered
         * to active outputs.</p>
         *
         * <p>The default implementation logs a notice to the system log
         * about the disconnection.</p>
         *
         * <p>You should clean up the camera with {@link CameraDevice#close} after
         * this happens, as it is not recoverable until opening the camera again
         * after it becomes {@link CameraManager.AvailabilityListener#onCameraAvailable available}.
         * </p>
         *
         * @param camera the device that has been disconnected
         */
        public abstract void onDisconnected(CameraDevice camera); // Must implement

        /**
         * The method called when a camera device has encountered a serious error.
         *
         * <p>This callback may be called instead of {@link #onOpened}
         * if opening the camera fails.</p>
         *
         * <p>This indicates a failure of the camera device or camera service in
         * some way. Any attempt to call methods on this CameraDevice in the
         * future will throw a {@link CameraAccessException} with the
         * {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason.
         * </p>
         *
         * <p>There may still be capture completion or camera stream listeners
         * that will be called after this error is received.</p>
         *
         * <p>You should clean up the camera with {@link CameraDevice#close} after
         * this happens. Further attempts at recovery are error-code specific.</p>
         *
         * @param camera The device reporting the error
         * @param error The error code, one of the
         *     {@code CameraDeviceListener.ERROR_*} values.
         *
         * @see #ERROR_CAMERA_DEVICE
         * @see #ERROR_CAMERA_SERVICE
         * @see #ERROR_CAMERA_DISABLED
         * @see #ERROR_CAMERA_IN_USE
         */
        public abstract void onError(CameraDevice camera, int error); // Must implement
    }

    /**
     * To be inherited by android.hardware.camera2.* code only.
     * @hide
     */
    public CameraDevice() {}
}
