/*
 * Copyright (C) 2014 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.impl;

import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.TaskDrainer;
import android.hardware.camera2.utils.TaskSingleDrainer;
import android.os.Binder;
import android.os.Handler;
import android.util.Log;
import android.view.Surface;

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

import static android.hardware.camera2.impl.CameraDeviceImpl.checkHandler;
import static com.android.internal.util.Preconditions.*;

public class CameraCaptureSessionImpl extends CameraCaptureSession
        implements CameraCaptureSessionCore {
    private static final String TAG = "CameraCaptureSession";
    private static final boolean DEBUG = false;

    /** Simple integer ID for session for debugging */
    private final int mId;
    private final String mIdString;

    /** Input surface configured by native camera framework based on user-specified configuration */
    private final Surface mInput;
    /**
     * User-specified state callback, used for outgoing events; calls to this object will be
     * automatically invoked via {@code mStateExecutor}.
     */
    private final CameraCaptureSession.StateCallback mStateCallback;
    /** User-specified state executor used for outgoing state callback events */
    private final Executor mStateExecutor;

    /** Internal camera device; used to translate calls into existing deprecated API */
    private final android.hardware.camera2.impl.CameraDeviceImpl mDeviceImpl;
    /** Internal executor; used for all incoming events to preserve total order */
    private final Executor mDeviceExecutor;

    /** Drain Sequence IDs which have been queued but not yet finished with aborted/completed */
    private final TaskDrainer<Integer> mSequenceDrainer;
    /** Drain state transitions from ACTIVE -> IDLE */
    private final TaskSingleDrainer mIdleDrainer;
    /** Drain state transitions from BUSY -> IDLE */
    private final TaskSingleDrainer mAbortDrainer;

    /** This session is closed; all further calls will throw ISE */
    private boolean mClosed = false;
    /** This session failed to be configured successfully */
    private final boolean mConfigureSuccess;
    /** Do not unconfigure if this is set; another session will overwrite configuration */
    private boolean mSkipUnconfigure = false;

    /** Is the session in the process of aborting? Pay attention to BUSY->IDLE transitions. */
    private volatile boolean mAborting;

    /**
     * Create a new CameraCaptureSession.
     *
     * <p>The camera device must already be in the {@code IDLE} state when this is invoked.
     * There must be no pending actions
     * (e.g. no pending captures, no repeating requests, no flush).</p>
     */
    CameraCaptureSessionImpl(int id, Surface input,
            CameraCaptureSession.StateCallback callback, Executor stateExecutor,
            android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
            Executor deviceStateExecutor, boolean configureSuccess) {
        if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }

        mId = id;
        mIdString = String.format("Session %d: ", mId);

        mInput = input;
        mStateExecutor = checkNotNull(stateExecutor, "stateExecutor must not be null");
        mStateCallback = createUserStateCallbackProxy(mStateExecutor, callback);

        mDeviceExecutor = checkNotNull(deviceStateExecutor,
                "deviceStateExecutor must not be null");
        mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null");

        /*
         * 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.
         */
        mSequenceDrainer = new TaskDrainer<>(mDeviceExecutor, new SequenceDrainListener(),
                /*name*/"seq");
        mIdleDrainer = new TaskSingleDrainer(mDeviceExecutor, new IdleDrainListener(),
                /*name*/"idle");
        mAbortDrainer = new TaskSingleDrainer(mDeviceExecutor, new AbortDrainListener(),
                /*name*/"abort");

        // CameraDevice should call configureOutputs and have it finish before constructing us

        if (configureSuccess) {
            mStateCallback.onConfigured(this);
            if (DEBUG) Log.v(TAG, mIdString + "Created session successfully");
            mConfigureSuccess = true;
        } else {
            mStateCallback.onConfigureFailed(this);
            mClosed = true; // do not fire any other callbacks, do not allow any other work
            Log.e(TAG, mIdString + "Failed to create capture session; configuration failed");
            mConfigureSuccess = false;
        }
    }

    @Override
    public CameraDevice getDevice() {
        return mDeviceImpl;
    }

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

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

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

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

    @Override
    public int capture(CaptureRequest request, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
        checkCaptureRequest(request);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            handler = checkHandler(handler, callback);

            if (DEBUG) {
                Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback +
                        " handler " + handler);
            }

            return addPendingSequence(mDeviceImpl.capture(request,
                    createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
        }
    }

    @Override
    public int captureSingleRequest(CaptureRequest request, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        if (executor == null) {
            throw new IllegalArgumentException("executor must not be null");
        } else if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }
        checkCaptureRequest(request);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            executor = CameraDeviceImpl.checkExecutor(executor, callback);

            if (DEBUG) {
                Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback +
                        " executor " + executor);
            }

            return addPendingSequence(mDeviceImpl.capture(request,
                    createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor));
        }
    }

    private void checkCaptureRequest(CaptureRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("request must not be null");
        } else if (request.isReprocess() && !isReprocessable()) {
            throw new IllegalArgumentException("this capture session cannot handle reprocess " +
                    "requests");
        } else if (request.isReprocess() && request.getReprocessableSessionId() != mId) {
            throw new IllegalArgumentException("capture request was created for another session");
        }
    }

    @Override
    public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
        checkCaptureRequests(requests);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            handler = checkHandler(handler, callback);

            if (DEBUG) {
                CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
                Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) +
                        ", callback " + callback + " handler " + handler);
            }

            return addPendingSequence(mDeviceImpl.captureBurst(requests,
                    createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
        }
    }

    @Override
    public int captureBurstRequests(List<CaptureRequest> requests, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        if (executor == null) {
            throw new IllegalArgumentException("executor must not be null");
        } else if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }
        checkCaptureRequests(requests);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            executor = CameraDeviceImpl.checkExecutor(executor, callback);

            if (DEBUG) {
                CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
                Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) +
                        ", callback " + callback + " executor " + executor);
            }

            return addPendingSequence(mDeviceImpl.captureBurst(requests,
                    createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor));
        }
    }

    private void checkCaptureRequests(List<CaptureRequest> requests) {
        if (requests == null) {
            throw new IllegalArgumentException("Requests must not be null");
        } else if (requests.isEmpty()) {
            throw new IllegalArgumentException("Requests must have at least one element");
        }

        for (CaptureRequest request : requests) {
            if (request.isReprocess()) {
                if (!isReprocessable()) {
                    throw new IllegalArgumentException("This capture session cannot handle " +
                            "reprocess requests");
                } else if (request.getReprocessableSessionId() != mId) {
                    throw new IllegalArgumentException("Capture request was created for another " +
                            "session");
                }
            }
        }

    }

    @Override
    public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
        checkRepeatingRequest(request);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            handler = checkHandler(handler, callback);

            if (DEBUG) {
                Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " +
                        callback + " handler" + " " + handler);
            }

            return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
                    createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
        }
    }

    @Override
    public int setSingleRepeatingRequest(CaptureRequest request, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        if (executor == null) {
            throw new IllegalArgumentException("executor must not be null");
        } else if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }
        checkRepeatingRequest(request);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            executor = CameraDeviceImpl.checkExecutor(executor, callback);

            if (DEBUG) {
                Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " +
                        callback + " executor" + " " + executor);
            }

            return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
                    createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor));
        }
    }

    private void checkRepeatingRequest(CaptureRequest request) {
        if (request == null) {
            throw new IllegalArgumentException("request must not be null");
        } else if (request.isReprocess()) {
            throw new IllegalArgumentException("repeating reprocess requests are not supported");
        }
    }

    @Override
    public int setRepeatingBurst(List<CaptureRequest> requests,
            CaptureCallback callback, Handler handler) throws CameraAccessException {
        checkRepeatingRequests(requests);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            handler = checkHandler(handler, callback);

            if (DEBUG) {
                CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
                Log.v(TAG, mIdString + "setRepeatingBurst - requests " +
                        Arrays.toString(requestArray) + ", callback " + callback +
                        " handler" + "" + handler);
            }

            return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
                    createCaptureCallbackProxy(handler, callback), mDeviceExecutor));
        }
    }

    @Override
    public int setRepeatingBurstRequests(List<CaptureRequest> requests, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        if (executor == null) {
            throw new IllegalArgumentException("executor must not be null");
        } else if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }
        checkRepeatingRequests(requests);

        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            executor = CameraDeviceImpl.checkExecutor(executor, callback);

            if (DEBUG) {
                CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
                Log.v(TAG, mIdString + "setRepeatingBurst - requests " +
                        Arrays.toString(requestArray) + ", callback " + callback +
                        " executor" + "" + executor);
            }

            return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
                    createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor));
        }
    }

    private void checkRepeatingRequests(List<CaptureRequest> requests) {
        if (requests == null) {
            throw new IllegalArgumentException("requests must not be null");
        } else if (requests.isEmpty()) {
            throw new IllegalArgumentException("requests must have at least one element");
        }

        for (CaptureRequest r : requests) {
            if (r.isReprocess()) {
                throw new IllegalArgumentException("repeating reprocess burst requests are not " +
                        "supported");
            }
        }
    }

    @Override
    public void stopRepeating() throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            if (DEBUG) {
                Log.v(TAG, mIdString + "stopRepeating");
            }

            mDeviceImpl.stopRepeating();
        }
    }

    @Override
    public void abortCaptures() throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            if (DEBUG) {
                Log.v(TAG, mIdString + "abortCaptures");
            }

            if (mAborting) {
                Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing");
                return;
            }

            mAborting = true;
            mAbortDrainer.taskStarted();

            mDeviceImpl.flush();
            // The next BUSY -> IDLE set of transitions will mark the end of the abort.
        }
    }

    @Override
    public void updateOutputConfiguration(OutputConfiguration config)
            throws CameraAccessException {
        synchronized (mDeviceImpl.mInterfaceLock) {
            checkNotClosed();

            if (DEBUG) {
                Log.v(TAG, mIdString + "updateOutputConfiguration");
            }

            mDeviceImpl.updateOutputConfiguration(config);
        }
    }

    @Override
    public boolean isReprocessable() {
        return mInput != null;
    }

    @Override
    public Surface getInputSurface() {
        return mInput;
    }

    /**
     * Replace this session with another session.
     *
     * <p>This is an optimization to avoid unconfiguring and then immediately having to
     * reconfigure again.</p>
     *
     * <p>The semantics are identical to {@link #close}, except that unconfiguring will be skipped.
     * <p>
     *
     * <p>After this call completes, the session will not call any further methods on the camera
     * device.</p>
     *
     * @see CameraCaptureSession#close
     */
    @Override
    public void replaceSessionClose() {
        synchronized (mDeviceImpl.mInterfaceLock) {
            /*
             * In order for creating new sessions to be fast, the new session should be created
             * before the old session is closed.
             *
             * Otherwise the old session will always unconfigure if there is no new session to
             * replace it.
             *
             * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt
             * to skip unconfigure if a new session is created before the captures are all drained,
             * but this would introduce nondeterministic behavior.
             */

            if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose");

            // Set up fast shutdown. Possible alternative paths:
            // - This session is active, so close() below starts the shutdown drain
            // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener.
            // - This session is already closed and has executed the idle drain listener, and
            //   configureOutputsChecked(null) has already been called.
            //
            // Do not call configureOutputsChecked(null) going forward, since it would race with the
            // configuration for the new session. If it was already called, then we don't care,
            // since it won't get called again.
            mSkipUnconfigure = true;
            close();
        }
    }

    @Override
    public void close() {
        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;

            /*
             * Flush out any repeating request. Since camera is closed, no new requests
             * can be queued, and eventually the entire request queue will be drained.
             *
             * If the camera device was already closed, short circuit and do nothing; since
             * no more internal device callbacks will fire anyway.
             *
             * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure
             * the camera. Once that's done, fire #onClosed.
             */
            try {
                mDeviceImpl.stopRepeating();
            } catch (IllegalStateException e) {
                // OK: Camera device may already be closed, nothing else to do

                // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
                // or just suppress the ISE only and rely onClosed.
                // Also skip any of the draining work if this is already closed.

                // Short-circuit; queue callback immediately and return
                mStateCallback.onClosed(this);
                return;
            } catch (CameraAccessException e) {
                // OK: close does not throw checked exceptions.
                Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);

                // TODO: call onError instead of onClosed if this happens
            }

            // If no sequences are pending, fire #onClosed immediately
            mSequenceDrainer.beginDrain();
        }
        if (mInput != null) {
            mInput.release();
        }
    }

    /**
     * Whether currently in mid-abort.
     *
     * <p>This is used by the implementation to set the capture failure
     * reason, in lieu of more accurate error codes from the camera service.
     * Unsynchronized to avoid deadlocks between simultaneous session->device,
     * device->session calls.</p>
     *
     */
    @Override
    public boolean isAborting() {
        return mAborting;
    }

    /**
     * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code executor}.
     */
    private StateCallback createUserStateCallbackProxy(Executor executor, StateCallback callback) {
        return new CallbackProxies.SessionStateCallbackProxy(executor, callback);
    }

    /**
     * Forward callbacks from
     * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback.
     *
     * <p>When a capture sequence finishes, update the pending checked sequences set.</p>
     */
    @SuppressWarnings("deprecation")
    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
            Handler handler, CaptureCallback callback) {
        final Executor executor = (callback != null) ? CameraDeviceImpl.checkAndWrapHandler(
                handler) : null;

        return createCaptureCallbackProxyWithExecutor(executor, callback);
    }

    private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxyWithExecutor(
            Executor executor, CaptureCallback callback) {
        return new CameraDeviceImpl.CaptureCallback() {
            @Override
            public void onCaptureStarted(CameraDevice camera,
                    CaptureRequest request, long timestamp, long frameNumber) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureStarted(
                                    CameraCaptureSessionImpl.this, request, timestamp,
                                    frameNumber));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }

            @Override
            public void onCapturePartial(CameraDevice camera,
                    CaptureRequest request, android.hardware.camera2.CaptureResult result) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCapturePartial(
                                    CameraCaptureSessionImpl.this, request, result));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }

            @Override
            public void onCaptureProgressed(CameraDevice camera,
                    CaptureRequest request, android.hardware.camera2.CaptureResult partialResult) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureProgressed(
                                    CameraCaptureSessionImpl.this, request, partialResult));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }

            @Override
            public void onCaptureCompleted(CameraDevice camera,
                    CaptureRequest request, android.hardware.camera2.TotalCaptureResult result) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureCompleted(
                                    CameraCaptureSessionImpl.this, request, result));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }

            @Override
            public void onCaptureFailed(CameraDevice camera,
                    CaptureRequest request, android.hardware.camera2.CaptureFailure failure) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureFailed(
                                    CameraCaptureSessionImpl.this, request, failure));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }

            @Override
            public void onCaptureSequenceCompleted(CameraDevice camera,
                    int sequenceId, long frameNumber) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureSequenceCompleted(
                                    CameraCaptureSessionImpl.this, sequenceId, frameNumber));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
                finishPendingSequence(sequenceId);
            }

            @Override
            public void onCaptureSequenceAborted(CameraDevice camera,
                    int sequenceId) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureSequenceAborted(
                                    CameraCaptureSessionImpl.this, sequenceId));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
                finishPendingSequence(sequenceId);
            }

            @Override
            public void onCaptureBufferLost(CameraDevice camera,
                    CaptureRequest request, Surface target, long frameNumber) {
                if ((callback != null) && (executor != null)) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> callback.onCaptureBufferLost(
                                    CameraCaptureSessionImpl.this, request, target, frameNumber));
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }
        };
    }

    /**
     *
     * Create an internal state callback, to be invoked on the mDeviceExecutor
     *
     * <p>It has a few behaviors:
     * <ul>
     * <li>Convert device state changes into session state changes.
     * <li>Keep track of async tasks that the session began (idle, abort).
     * </ul>
     * </p>
     * */
    @Override
    public CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() {
        final CameraCaptureSession session = this;
        final Object interfaceLock = mDeviceImpl.mInterfaceLock;


        return new CameraDeviceImpl.StateCallbackKK() {
            private boolean mBusy = false;
            private boolean mActive = false;

            @Override
            public void onOpened(CameraDevice camera) {
                throw new AssertionError("Camera must already be open before creating a session");
            }

            @Override
            public void onDisconnected(CameraDevice camera) {
                if (DEBUG) Log.v(TAG, mIdString + "onDisconnected");
                close();
            }

            @Override
            public void onError(CameraDevice camera, int error) {
                // Should not be reached, handled by device code
                Log.wtf(TAG, mIdString + "Got device error " + error);
            }

            @Override
            public void onActive(CameraDevice camera) {
                mIdleDrainer.taskStarted();
                mActive = true;

                if (DEBUG) Log.v(TAG, mIdString + "onActive");
                mStateCallback.onActive(session);
            }

            @Override
            public void onIdle(CameraDevice camera) {
                boolean isAborting;
                if (DEBUG) Log.v(TAG, mIdString + "onIdle");

                synchronized (interfaceLock) {
                    isAborting = mAborting;
                }

                /*
                 * Check which states we transitioned through:
                 *
                 * (ACTIVE -> IDLE)
                 * (BUSY -> IDLE)
                 *
                 * Note that this is also legal:
                 * (ACTIVE -> BUSY -> IDLE)
                 *
                 * and mark those tasks as finished
                 */
                if (mBusy && isAborting) {
                    mAbortDrainer.taskFinished();

                    synchronized (interfaceLock) {
                        mAborting = false;
                    }
                }

                if (mActive) {
                    mIdleDrainer.taskFinished();
                }

                mBusy = false;
                mActive = false;

                mStateCallback.onReady(session);
            }

            @Override
            public void onBusy(CameraDevice camera) {
                mBusy = true;

                // TODO: Queue captures during abort instead of failing them
                // since the app won't be able to distinguish the two actives
                // Don't signal the application since there's no clean mapping here
                if (DEBUG) Log.v(TAG, mIdString + "onBusy");
            }

            @Override
            public void onUnconfigured(CameraDevice camera) {
                if (DEBUG) Log.v(TAG, mIdString + "onUnconfigured");
            }

            @Override
            public void onRequestQueueEmpty() {
                if (DEBUG) Log.v(TAG, mIdString + "onRequestQueueEmpty");
                mStateCallback.onCaptureQueueEmpty(session);
            }

            @Override
            public void onSurfacePrepared(Surface surface) {
                if (DEBUG) Log.v(TAG, mIdString + "onSurfacePrepared");
                mStateCallback.onSurfacePrepared(session, surface);
            }
        };

    }

    @Override
    protected void finalize() throws Throwable {
        try {
            close();
        } finally {
            super.finalize();
        }
    }

    private void checkNotClosed() {
        if (mClosed) {
            throw new IllegalStateException(
                    "Session has been closed; further changes are illegal.");
        }
    }

    /**
     * Notify the session that a pending capture sequence has just been queued.
     *
     * <p>During a shutdown/close, the session waits until all pending sessions are finished
     * before taking any further steps to shut down itself.</p>
     *
     * @see #finishPendingSequence
     */
    private int addPendingSequence(int sequenceId) {
        mSequenceDrainer.taskStarted(sequenceId);
        return sequenceId;
    }

    /**
     * Notify the session that a pending capture sequence is now finished.
     *
     * <p>During a shutdown/close, once all pending sequences finish, it is safe to
     * close the camera further by unconfiguring and then firing {@code onClosed}.</p>
     */
    private void finishPendingSequence(int sequenceId) {
        try {
            mSequenceDrainer.taskFinished(sequenceId);
        } catch (IllegalStateException e) {
            // Workaround for b/27870771
            Log.w(TAG, e.getMessage());
        }
    }

    private class SequenceDrainListener implements TaskDrainer.DrainListener {
        @Override
        public void onDrained() {
            /*
             * No repeating request is set; and the capture queue has fully drained.
             *
             * If no captures were queued to begin with, and an abort was queued,
             * it's still possible to get another BUSY before the last IDLE.
             *
             * If the camera is already "IDLE" and no aborts are pending,
             * then the drain immediately finishes.
             */
            if (DEBUG) Log.v(TAG, mIdString + "onSequenceDrained");


            // Fire session close as soon as all sequences are complete.
            // We may still need to unconfigure the device, but a new session might be created
            // past this point, and notifications would then stop to this instance.
            mStateCallback.onClosed(CameraCaptureSessionImpl.this);

            // Fast path: A new capture session has replaced this one; don't wait for abort/idle
            // as we won't get state updates any more anyway.
            if (mSkipUnconfigure) {
                return;
            }

            mAbortDrainer.beginDrain();
        }
    }

    private class AbortDrainListener implements TaskDrainer.DrainListener {
        @Override
        public void onDrained() {
            if (DEBUG) Log.v(TAG, mIdString + "onAbortDrained");
            synchronized (mDeviceImpl.mInterfaceLock) {
                /*
                 * Any queued aborts have now completed.
                 *
                 * It's now safe to wait to receive the final "IDLE" event, as the camera device
                 * will no longer again transition to "ACTIVE" by itself.
                 *
                 * If the camera is already "IDLE", then the drain immediately finishes.
                 */

                // Fast path: A new capture session has replaced this one; don't wait for idle
                // as we won't get state updates any more anyway.
                if (mSkipUnconfigure) {
                    return;
                }
                mIdleDrainer.beginDrain();
            }
        }
    }

    private class IdleDrainListener implements TaskDrainer.DrainListener {
        @Override
        public void onDrained() {
            if (DEBUG) Log.v(TAG, mIdString + "onIdleDrained");

            // Take device lock before session lock so that we can call back into device
            // without causing a deadlock
            synchronized (mDeviceImpl.mInterfaceLock) {
                /*
                 * The device is now IDLE, and has settled. It will not transition to
                 * ACTIVE or BUSY again by itself.
                 *
                 * It's now safe to unconfigure the outputs.
                 *
                 * This operation is idempotent; a session will not be closed twice.
                 */
                if (DEBUG)
                    Log.v(TAG, mIdString + "Session drain complete, skip unconfigure: " +
                            mSkipUnconfigure);

                // Fast path: A new capture session has replaced this one; don't wait for idle
                // as we won't get state updates any more anyway.
                if (mSkipUnconfigure) {
                    return;
                }

                // Final slow path: unconfigure the camera, no session has replaced us and
                // everything is idle.
                try {
                    // begin transition to unconfigured
                    mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
                            /*operatingMode*/ ICameraDeviceUser.NORMAL_MODE,
                            /*sessionParams*/ null);
                } catch (CameraAccessException e) {
                    // OK: do not throw checked exceptions.
                    Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);

                    // TODO: call onError instead of onClosed if this happens
                } catch (IllegalStateException e) {
                    // Camera is already closed, so nothing left to do
                    if (DEBUG) Log.v(TAG, mIdString +
                            "Camera was already closed or busy, skipping unconfigure");
                }
            }
        }
    }

}
