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

package android.hardware.camera2.impl;

import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraOfflineSession;
import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraOfflineSession;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.params.OutputConfiguration;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.Range;
import android.util.SparseArray;
import android.view.Surface;

import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.Executor;

import static com.android.internal.util.Preconditions.*;

public class CameraOfflineSessionImpl extends CameraOfflineSession
        implements IBinder.DeathRecipient {
    private static final String TAG = "CameraOfflineSessionImpl";
    private static final int REQUEST_ID_NONE = -1;
    private static final long NANO_PER_SECOND = 1000000000; //ns
    private final boolean DEBUG = false;

    private ICameraOfflineSession mRemoteSession;
    private final AtomicBoolean mClosing = new AtomicBoolean();

    private SimpleEntry<Integer, InputConfiguration> mOfflineInput =
            new SimpleEntry<>(REQUEST_ID_NONE, null);
    private SparseArray<OutputConfiguration> mOfflineOutputs = new SparseArray<>();
    private SparseArray<OutputConfiguration> mConfiguredOutputs = new SparseArray<>();

    final Object mInterfaceLock = new Object(); // access from this class and Session only!

    private final String mCameraId;
    private final CameraCharacteristics mCharacteristics;
    private final int mTotalPartialCount;

    private final Executor mOfflineExecutor;
    private final CameraOfflineSessionCallback mOfflineCallback;

    private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();

    /**
     * A list tracking request and its expected last regular/reprocess/zslStill frame
     * number.
     */
    private List<RequestLastFrameNumbersHolder> mOfflineRequestLastFrameNumbersList =
            new ArrayList<>();

    /**
     * An object tracking received frame numbers.
     * Updated when receiving callbacks from ICameraDeviceCallbacks.
     */
    private FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();

    /** map request IDs to callback/request data */
    private SparseArray<CaptureCallbackHolder> mCaptureCallbackMap =
            new SparseArray<CaptureCallbackHolder>();

    public CameraOfflineSessionImpl(String cameraId, CameraCharacteristics characteristics,
            Executor offlineExecutor, CameraOfflineSessionCallback offlineCallback,
            SparseArray<OutputConfiguration> offlineOutputs,
            SimpleEntry<Integer, InputConfiguration> offlineInput,
            SparseArray<OutputConfiguration> configuredOutputs,
            FrameNumberTracker frameNumberTracker, SparseArray<CaptureCallbackHolder> callbackMap,
            List<RequestLastFrameNumbersHolder> frameNumberList) {
        if ((cameraId == null) || (characteristics == null)) {
            throw new IllegalArgumentException("Null argument given");
        }

        mCameraId = cameraId;
        mCharacteristics = characteristics;

        Integer partialCount =
                mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT);
        if (partialCount == null) {
            // 1 means partial result is not supported.
            mTotalPartialCount = 1;
        } else {
            mTotalPartialCount = partialCount;
        }

        mOfflineRequestLastFrameNumbersList.addAll(frameNumberList);
        mFrameNumberTracker = frameNumberTracker;
        mCaptureCallbackMap = callbackMap;
        mConfiguredOutputs = configuredOutputs;
        mOfflineOutputs = offlineOutputs;
        mOfflineInput = offlineInput;
        mOfflineExecutor = checkNotNull(offlineExecutor, "offline executor must not be null");
        mOfflineCallback = checkNotNull(offlineCallback, "offline callback must not be null");

    }

    public CameraDeviceCallbacks getCallbacks() {
        return mCallbacks;
    }

    public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
        @Override
        public IBinder asBinder() {
            return this;
        }

        @Override
        public void onDeviceError(final int errorCode, CaptureResultExtras resultExtras) {
            synchronized(mInterfaceLock) {

                switch (errorCode) {
                    case CameraDeviceCallbacks.ERROR_CAMERA_REQUEST:
                    case CameraDeviceCallbacks.ERROR_CAMERA_RESULT:
                    case CameraDeviceCallbacks.ERROR_CAMERA_BUFFER:
                        onCaptureErrorLocked(errorCode, resultExtras);
                        break;
                    default:
                        Runnable errorDispatch = new Runnable() {
                            @Override
                            public void run() {
                                if (!isClosed()) {
                                    mOfflineCallback.onError(CameraOfflineSessionImpl.this,
                                            CameraOfflineSessionCallback.STATUS_INTERNAL_ERROR);
                                }
                            }
                        };

                        final long ident = Binder.clearCallingIdentity();
                        try {
                            mOfflineExecutor.execute(errorDispatch);
                        } finally {
                            Binder.restoreCallingIdentity(ident);
                        }
                }
            }
        }

        @Override
        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
            Log.e(TAG, "Unexpected repeating request error received. Last frame number is " +
                    lastFrameNumber);
        }

        @Override
        public void onDeviceIdle() {
            synchronized(mInterfaceLock) {
                if (mRemoteSession == null) {
                    Log.v(TAG, "Ignoring idle state notifications during offline switches");
                    return;
                }

                Runnable idleDispatch = new Runnable() {
                    @Override
                    public void run() {
                        if (!isClosed()) {
                            mOfflineCallback.onIdle(CameraOfflineSessionImpl.this);
                        }
                    }
                };

                final long ident = Binder.clearCallingIdentity();
                try {
                    mOfflineExecutor.execute(idleDispatch);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
        }

        @Override
        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
            int requestId = resultExtras.getRequestId();
            final long frameNumber = resultExtras.getFrameNumber();

            final CaptureCallbackHolder holder;

            synchronized(mInterfaceLock) {
                // Get the callback for this frame ID, if there is one
                holder = CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);

                if (holder == null) {
                    return;
                }

                final Executor executor = holder.getCallback().getExecutor();
                if (isClosed() || (executor == null)) return;

                // Dispatch capture start notice
                final long ident = Binder.clearCallingIdentity();
                try {
                    executor.execute(
                        new Runnable() {
                            @Override
                            public void run() {
                                final CameraCaptureSession.CaptureCallback callback =
                                        holder.getCallback().getSessionCallback();
                                if (!CameraOfflineSessionImpl.this.isClosed() &&
                                        (callback != null)) {
                                    final int subsequenceId = resultExtras.getSubsequenceId();
                                    final CaptureRequest request = holder.getRequest(subsequenceId);

                                    if (holder.hasBatchedOutputs()) {
                                        // Send derived onCaptureStarted for requests within the
                                        // batch
                                        final Range<Integer> fpsRange =
                                                request.get(
                                                        CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
                                        for (int i = 0; i < holder.getRequestCount(); i++) {
                                            final CaptureRequest cbRequest = holder.getRequest(i);
                                            final long cbTimestamp =
                                                        timestamp - (subsequenceId - i) *
                                                        NANO_PER_SECOND/fpsRange.getUpper();
                                            final long cbFrameNumber =
                                                    frameNumber - (subsequenceId - i);
                                            callback.onCaptureStarted(CameraOfflineSessionImpl.this,
                                                    cbRequest, cbTimestamp, cbFrameNumber);
                                        }
                                    } else {
                                        callback.onCaptureStarted(CameraOfflineSessionImpl.this,
                                                holder.getRequest(
                                                    resultExtras.getSubsequenceId()),
                                                timestamp, frameNumber);
                                    }
                                }
                            }
                        });
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
        }

        @Override
        public void onResultReceived(CameraMetadataNative result,
                CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[])
                throws RemoteException {

            int requestId = resultExtras.getRequestId();
            long frameNumber = resultExtras.getFrameNumber();

            synchronized(mInterfaceLock) {
                // TODO: Handle CameraCharacteristics access from CaptureResult correctly.
                result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE,
                        mCharacteristics.get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));

                final CaptureCallbackHolder holder =
                        CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);
                final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId());

                boolean isPartialResult =
                        (resultExtras.getPartialResultCount() < mTotalPartialCount);
                int requestType = request.getRequestType();

                // Check if we have a callback for this
                if (holder == null) {
                    mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult,
                            requestType);

                    return;
                }

                if (isClosed()) {
                    mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult,
                            requestType);
                    return;
                }


                Runnable resultDispatch = null;

                CaptureResult finalResult;
                // Make a copy of the native metadata before it gets moved to a CaptureResult
                // object.
                final CameraMetadataNative resultCopy;
                if (holder.hasBatchedOutputs()) {
                    resultCopy = new CameraMetadataNative(result);
                } else {
                    resultCopy = null;
                }

                final Executor executor = holder.getCallback().getExecutor();
                // Either send a partial result or the final capture completed result
                if (isPartialResult) {
                    final CaptureResult resultAsCapture =
                            new CaptureResult(result, request, resultExtras);
                    // Partial result
                    resultDispatch = new Runnable() {
                        @Override
                        public void run() {
                            final CameraCaptureSession.CaptureCallback callback =
                                    holder.getCallback().getSessionCallback();
                            if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
                                if (holder.hasBatchedOutputs()) {
                                    // Send derived onCaptureProgressed for requests within
                                    // the batch.
                                    for (int i = 0; i < holder.getRequestCount(); i++) {
                                        CameraMetadataNative resultLocal =
                                                new CameraMetadataNative(resultCopy);
                                        final CaptureResult resultInBatch = new CaptureResult(
                                                resultLocal, holder.getRequest(i), resultExtras);

                                        final CaptureRequest cbRequest = holder.getRequest(i);
                                        callback.onCaptureProgressed(CameraOfflineSessionImpl.this,
                                                cbRequest, resultInBatch);
                                    }
                                } else {
                                    callback.onCaptureProgressed(CameraOfflineSessionImpl.this,
                                            request, resultAsCapture);
                                }
                            }
                        }
                    };
                    finalResult = resultAsCapture;
                } else {
                    List<CaptureResult> partialResults =
                            mFrameNumberTracker.popPartialResults(frameNumber);

                    final long sensorTimestamp =
                            result.get(CaptureResult.SENSOR_TIMESTAMP);
                    final Range<Integer> fpsRange =
                            request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
                    final int subsequenceId = resultExtras.getSubsequenceId();
                    final TotalCaptureResult resultAsCapture = new TotalCaptureResult(result,
                            request, resultExtras, partialResults, holder.getSessionId(),
                            physicalResults);
                    // Final capture result
                    resultDispatch = new Runnable() {
                        @Override
                        public void run() {
                            final CameraCaptureSession.CaptureCallback callback =
                                    holder.getCallback().getSessionCallback();
                            if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
                                if (holder.hasBatchedOutputs()) {
                                    // Send derived onCaptureCompleted for requests within
                                    // the batch.
                                    for (int i = 0; i < holder.getRequestCount(); i++) {
                                        resultCopy.set(CaptureResult.SENSOR_TIMESTAMP,
                                                sensorTimestamp - (subsequenceId - i) *
                                                NANO_PER_SECOND/fpsRange.getUpper());
                                        CameraMetadataNative resultLocal =
                                                new CameraMetadataNative(resultCopy);
                                        // No logical multi-camera support for batched output mode.
                                        TotalCaptureResult resultInBatch = new TotalCaptureResult(
                                            resultLocal, holder.getRequest(i), resultExtras,
                                            partialResults, holder.getSessionId(),
                                            new PhysicalCaptureResultInfo[0]);

                                        final CaptureRequest cbRequest = holder.getRequest(i);
                                        callback.onCaptureCompleted(CameraOfflineSessionImpl.this,
                                                cbRequest, resultInBatch);
                                    }
                                } else {
                                    callback.onCaptureCompleted(CameraOfflineSessionImpl.this,
                                            request, resultAsCapture);
                                }
                            }
                        }
                    };
                    finalResult = resultAsCapture;
                }

                if (executor != null) {
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(resultDispatch);
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }

                // Collect the partials for a total result; or mark the frame as totally completed
                mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult,
                        requestType);

                // Fire onCaptureSequenceCompleted
                if (!isPartialResult) {
                    checkAndFireSequenceComplete();
                }
            }
        }

        @Override
        public void onPrepared(int streamId) {
            Log.e(TAG, "Unexpected stream " + streamId + " is prepared");
        }

        @Override
        public void onRequestQueueEmpty() {
            // No-op during offline mode
            Log.v(TAG, "onRequestQueueEmpty");
        }

        /**
         * Called by onDeviceError for handling single-capture failures.
         */
        private void onCaptureErrorLocked(int errorCode, CaptureResultExtras resultExtras) {
            final int requestId = resultExtras.getRequestId();
            final int subsequenceId = resultExtras.getSubsequenceId();
            final long frameNumber = resultExtras.getFrameNumber();
            final String errorPhysicalCameraId = resultExtras.getErrorPhysicalCameraId();
            final CaptureCallbackHolder holder =
                    CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);

            if (holder == null) {
                Log.e(TAG, String.format("Receive capture error on unknown request ID %d",
                        requestId));
                return;
            }

            final CaptureRequest request = holder.getRequest(subsequenceId);

            Runnable failureDispatch = null;
            if (errorCode == ERROR_CAMERA_BUFFER) {
                // Because 1 stream id could map to multiple surfaces, we need to specify both
                // streamId and surfaceId.
                OutputConfiguration config;
                if ((mRemoteSession == null) && !isClosed()) {
                    config = mConfiguredOutputs.get(resultExtras.getErrorStreamId());
                } else {
                    config = mOfflineOutputs.get(resultExtras.getErrorStreamId());
                }
                if (config == null) {
                    Log.v(TAG, String.format(
                            "Stream %d has been removed. Skipping buffer lost callback",
                            resultExtras.getErrorStreamId()));
                    return;
                }
                for (Surface surface : config.getSurfaces()) {
                    if (!request.containsTarget(surface)) {
                        continue;
                    }
                    final Executor executor = holder.getCallback().getExecutor();
                    failureDispatch = new Runnable() {
                        @Override
                        public void run() {
                            final CameraCaptureSession.CaptureCallback callback =
                                    holder.getCallback().getSessionCallback();
                            if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
                                callback.onCaptureBufferLost( CameraOfflineSessionImpl.this,
                                        request, surface, frameNumber);
                            }
                        }
                    };
                    if (executor != null) {
                        // Dispatch the failure callback
                        final long ident = Binder.clearCallingIdentity();
                        try {
                            executor.execute(failureDispatch);
                        } finally {
                            Binder.restoreCallingIdentity(ident);
                        }
                    }
                }
            } else {
                boolean mayHaveBuffers = (errorCode == ERROR_CAMERA_RESULT);
                int reason = CaptureFailure.REASON_ERROR;

                final CaptureFailure failure = new CaptureFailure(
                    request,
                    reason,
                    /*dropped*/ mayHaveBuffers,
                    requestId,
                    frameNumber,
                    errorPhysicalCameraId);

                final Executor executor = holder.getCallback().getExecutor();
                failureDispatch = new Runnable() {
                    @Override
                    public void run() {
                        final CameraCaptureSession.CaptureCallback callback =
                                holder.getCallback().getSessionCallback();
                        if (!CameraOfflineSessionImpl.this.isClosed() && (callback != null)) {
                            callback.onCaptureFailed(CameraOfflineSessionImpl.this, request,
                                    failure);
                        }
                    }
                };

                // Fire onCaptureSequenceCompleted if appropriate
                mFrameNumberTracker.updateTracker(frameNumber,
                        /*error*/true, request.getRequestType());
                checkAndFireSequenceComplete();

                if (executor != null) {
                    // Dispatch the failure callback
                    final long ident = Binder.clearCallingIdentity();
                    try {
                        executor.execute(failureDispatch);
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                }
            }

        }

    }

    private void checkAndFireSequenceComplete() {
        long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
        long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
        long completedZslStillFrameNumber = mFrameNumberTracker.getCompletedZslStillFrameNumber();
        Iterator<RequestLastFrameNumbersHolder> iter =
                mOfflineRequestLastFrameNumbersList.iterator();
        while (iter.hasNext()) {
            final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
            boolean sequenceCompleted = false;
            final int requestId = requestLastFrameNumbers.getRequestId();
            final CaptureCallbackHolder holder;
            final Executor executor;
            final CameraCaptureSession.CaptureCallback callback;
            synchronized(mInterfaceLock) {
                int index = mCaptureCallbackMap.indexOfKey(requestId);
                holder = (index >= 0) ?
                        mCaptureCallbackMap.valueAt(index) : null;
                if (holder != null) {
                    long lastRegularFrameNumber =
                            requestLastFrameNumbers.getLastRegularFrameNumber();
                    long lastReprocessFrameNumber =
                            requestLastFrameNumbers.getLastReprocessFrameNumber();
                    long lastZslStillFrameNumber =
                            requestLastFrameNumbers.getLastZslStillFrameNumber();
                    executor = holder.getCallback().getExecutor();
                    callback = holder.getCallback().getSessionCallback();
                    // check if it's okay to remove request from mCaptureCallbackMap
                    if (lastRegularFrameNumber <= completedFrameNumber
                            && lastReprocessFrameNumber <= completedReprocessFrameNumber
                            && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
                        sequenceCompleted = true;
                        mCaptureCallbackMap.removeAt(index);
                    }
                } else {
                    executor = null;
                    callback = null;
                }
            }

            // If no callback is registered for this requestId or sequence completed, remove it
            // from the frame number->request pair because it's not needed anymore.
            if (holder == null || sequenceCompleted) {
                iter.remove();
            }

            // Call onCaptureSequenceCompleted
            if ((sequenceCompleted) && (callback != null) && (executor != null)) {
                Runnable resultDispatch = new Runnable() {
                    @Override
                    public void run() {
                        if (!isClosed()) {
                            callback.onCaptureSequenceCompleted(CameraOfflineSessionImpl.this,
                                    requestId, requestLastFrameNumbers.getLastFrameNumber());
                        }
                    }
                };

                final long ident = Binder.clearCallingIdentity();
                try {
                    executor.execute(resultDispatch);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }

                if (mCaptureCallbackMap.size() == 0) {
                    getCallbacks().onDeviceIdle();
                }
            }

        }
    }

    public void notifyFailedSwitch() {
        synchronized(mInterfaceLock) {
            Runnable switchFailDispatch = new Runnable() {
                @Override
                public void run() {
                    mOfflineCallback.onSwitchFailed(CameraOfflineSessionImpl.this);
                }
            };

            final long ident = Binder.clearCallingIdentity();
            try {
                mOfflineExecutor.execute(switchFailDispatch);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

    /**
     * Set remote session.
     *
     */
    public void setRemoteSession(ICameraOfflineSession remoteSession) throws CameraAccessException {
        synchronized(mInterfaceLock) {
            if (remoteSession == null) {
                notifyFailedSwitch();
                return;
            }

            mRemoteSession = remoteSession;

            IBinder remoteSessionBinder = remoteSession.asBinder();
            if (remoteSessionBinder == null) {
                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "The camera offline session has encountered a serious error");
            }

            try {
                remoteSessionBinder.linkToDeath(this, /*flag*/ 0);
            } catch (RemoteException e) {
                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "The camera offline session has encountered a serious error");
            }

            Runnable readyDispatch = new Runnable() {
                @Override
                public void run() {
                    if (!isClosed()) {
                        mOfflineCallback.onReady(CameraOfflineSessionImpl.this);
                    }
                }
            };

            final long ident = Binder.clearCallingIdentity();
            try {
                mOfflineExecutor.execute(readyDispatch);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

    /** Whether the offline session has started to close (may not yet have finished) */
    private boolean isClosed() {
        return mClosing.get();
    }

    private void disconnect() {
        synchronized (mInterfaceLock) {
            if (mClosing.getAndSet(true)) {
                return;
            }

            if (mRemoteSession != null) {
                mRemoteSession.asBinder().unlinkToDeath(this, /*flags*/0);

                try {
                    mRemoteSession.disconnect();
                } catch (RemoteException e) {
                    Log.e(TAG, "Exception while disconnecting from offline session: ", e);
                }
            } else {
                throw new IllegalStateException("Offline session is not yet ready");
            }

            mRemoteSession = null;

            Runnable closeDispatch = new Runnable() {
                @Override
                public void run() {
                    mOfflineCallback.onClosed(CameraOfflineSessionImpl.this);
                }
            };

            final long ident = Binder.clearCallingIdentity();
            try {
                mOfflineExecutor.execute(closeDispatch);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

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

    /**
     * Listener for binder death.
     *
     * <p> Handle binder death for ICameraOfflineSession.</p>
     */
    @Override
    public void binderDied() {
        Log.w(TAG, "CameraOfflineSession on device " + mCameraId + " died unexpectedly");
        disconnect();
    }

    @Override
    public CameraDevice getDevice() {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void prepare(Surface surface) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void prepare(int maxCount, Surface surface) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void tearDown(Surface surface) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void finalizeOutputConfigurations(
            List<OutputConfiguration> outputConfigs) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int capture(CaptureRequest request, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int captureSingleRequest(CaptureRequest request, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int captureBurstRequests(List<CaptureRequest> requests, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
            Handler handler) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int setSingleRepeatingRequest(CaptureRequest request, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int setRepeatingBurst(List<CaptureRequest> requests,
            CaptureCallback callback, Handler handler) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public int setRepeatingBurstRequests(List<CaptureRequest> requests, Executor executor,
            CaptureCallback callback) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void stopRepeating() throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void abortCaptures() throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void updateOutputConfiguration(OutputConfiguration config)
            throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public boolean isReprocessable() {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public Surface getInputSurface() {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public CameraOfflineSession switchToOffline(Collection<Surface> offlineOutputs,
            Executor executor, CameraOfflineSessionCallback listener) throws CameraAccessException {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public boolean supportsOfflineProcessing(Surface surface) {
        throw new UnsupportedOperationException("Operation not supported in offline mode");
    }

    @Override
    public void close() {
        disconnect();
    }
}
