1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/*
2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project
3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License.
6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at
7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and
14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License.
15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpackage android.hardware.camera2.legacy;
18feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
194aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunkimport android.hardware.camera2.impl.CameraDeviceImpl;
20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.impl.CameraMetadataNative;
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.os.Handler;
22feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log;
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Emulates a the state of a single Camera2 device.
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>
28feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * This class acts as the state machine for a camera device.  Valid state transitions are given
29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * in the table below:
30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </p>
31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <ul>
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      <li>{@code UNCONFIGURED -> CONFIGURING}</li>
34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      <li>{@code CONFIGURING -> IDLE}</li>
35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      <li>{@code IDLE -> CONFIGURING}</li>
36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      <li>{@code IDLE -> CAPTURING}</li>
37d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk *      <li>{@code IDLE -> IDLE}</li>
38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      <li>{@code CAPTURING -> IDLE}</li>
39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      <li>{@code ANY -> ERROR}</li>
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * </ul>
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
42feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class CameraDeviceState {
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final String TAG = "CameraDeviceState";
44a78791f22af6c6985d186494737468bb19b69540Eino-Ville Talvala    private static final boolean DEBUG = false;
45feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
46feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final int STATE_ERROR = 0;
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final int STATE_UNCONFIGURED = 1;
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final int STATE_CONFIGURING = 2;
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final int STATE_IDLE = 3;
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final int STATE_CAPTURING = 4;
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
52e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    private static final String[] sStateNames = { "ERROR", "UNCONFIGURED", "CONFIGURING", "IDLE",
53e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            "CAPTURING"};
54e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private int mCurrentState = STATE_UNCONFIGURED;
564aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk    private int mCurrentError = NO_CAPTURE_ERROR;
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private RequestHolder mCurrentRequest = null;
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private Handler mCurrentHandler = null;
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private CameraDeviceStateListener mCurrentListener = null;
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
63e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    /**
64e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * Error code used by {@link #setCaptureStart} and {@link #setCaptureResult} to indicate that no
65e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * error has occurred.
66e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     */
67e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    public static final int NO_CAPTURE_ERROR = -1;
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * CameraDeviceStateListener callbacks to be called after state transitions.
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public interface CameraDeviceStateListener {
73385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala        void onError(int errorCode, Object errorArg, RequestHolder holder);
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        void onConfiguring();
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        void onIdle();
7651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        void onBusy();
7791838ded36131525312739c0929913b215519c2aRuben Brunk        void onCaptureStarted(RequestHolder holder, long timestamp);
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        void onCaptureResult(CameraMetadataNative result, RequestHolder holder);
792da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen        void onRepeatingRequestError(long lastFrameNumber);
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
83feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Transition to the {@code ERROR} state.
84feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>
86feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * The device cannot exit the {@code ERROR} state.  If the device was not already in the
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * {@code ERROR} state, {@link CameraDeviceStateListener#onError(int, RequestHolder)} will be
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * called.
89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * </p>
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param error the error to set.  Should be one of the error codes defined in
924aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk     *      {@link CameraDeviceImpl.CameraDeviceCallbacks}.
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
94feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public synchronized void setError(int error) {
95feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCurrentError = error;
96feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        doStateTransition(STATE_ERROR);
97feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
98feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
99feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
100feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Transition to the {@code CONFIGURING} state, or {@code ERROR} if in an invalid state.
101feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
102feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>
103feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * If the device was not already in the {@code CONFIGURING} state,
104feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * {@link CameraDeviceStateListener#onConfiguring()} will be called.
105feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * </p>
106feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
1074aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk     * @return {@code false} if an error has occurred.
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
1094aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk    public synchronized boolean setConfiguring() {
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        doStateTransition(STATE_CONFIGURING);
1114aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        return mCurrentError == NO_CAPTURE_ERROR;
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Transition to the {@code IDLE} state, or {@code ERROR} if in an invalid state.
116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>
118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * If the device was not already in the {@code IDLE} state,
119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * {@link CameraDeviceStateListener#onIdle()} will be called.
120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * </p>
121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
1224aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk     * @return {@code false} if an error has occurred.
123feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
1244aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk    public synchronized boolean setIdle() {
125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        doStateTransition(STATE_IDLE);
1264aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        return mCurrentError == NO_CAPTURE_ERROR;
127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
128feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
129feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Transition to the {@code CAPTURING} state, or {@code ERROR} if in an invalid state.
131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
132feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>
133feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * If the device was not already in the {@code CAPTURING} state,
134feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * {@link CameraDeviceStateListener#onCaptureStarted(RequestHolder)} will be called.
135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * </p>
136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param request A {@link RequestHolder} containing the request for the current capture.
13891838ded36131525312739c0929913b215519c2aRuben Brunk     * @param timestamp The timestamp of the capture start in nanoseconds.
139e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * @param captureError Report a recoverable error for a single request using a valid
140e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *                     error code for {@code ICameraDeviceCallbacks}, or
141e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *                     {@link #NO_CAPTURE_ERROR}
1424aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk     * @return {@code false} if an error has occurred.
143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
1444aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk    public synchronized boolean setCaptureStart(final RequestHolder request, long timestamp,
145e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                                            int captureError) {
146feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCurrentRequest = request;
147e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        doStateTransition(STATE_CAPTURING, timestamp, captureError);
1484aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        return mCurrentError == NO_CAPTURE_ERROR;
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Set the result for a capture.
153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
154feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>
155feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * If the device was in the {@code CAPTURING} state,
156feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * {@link CameraDeviceStateListener#onCaptureResult(CameraMetadataNative, RequestHolder)} will
157feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * be called with the given result, otherwise this will result in the device transitioning to
158feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * the {@code ERROR} state,
159feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * </p>
160feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
161e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * @param request The {@link RequestHolder} request that created this result.
162e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * @param result The {@link CameraMetadataNative} result to set.
163e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * @param captureError Report a recoverable error for a single buffer or result using a valid
164e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *                     error code for {@code ICameraDeviceCallbacks}, or
165e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *                     {@link #NO_CAPTURE_ERROR}.
166385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala     * @param captureErrorArg An argument for some error captureError codes.
1674aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk     * @return {@code false} if an error has occurred.
168feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
1694aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk    public synchronized boolean setCaptureResult(final RequestHolder request,
170385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala            final CameraMetadataNative result,
171385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala            final int captureError, final Object captureErrorArg) {
172feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (mCurrentState != STATE_CAPTURING) {
173feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
1744aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk            mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
175feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            doStateTransition(STATE_ERROR);
1764aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk            return mCurrentError == NO_CAPTURE_ERROR;
177feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
178feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
179feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (mCurrentHandler != null && mCurrentListener != null) {
180e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            if (captureError != NO_CAPTURE_ERROR) {
181e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                mCurrentHandler.post(new Runnable() {
182e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    @Override
183e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    public void run() {
184385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala                        mCurrentListener.onError(captureError, captureErrorArg, request);
185e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    }
186e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                });
187e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            } else {
188e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                mCurrentHandler.post(new Runnable() {
189e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    @Override
190e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    public void run() {
191e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        mCurrentListener.onCaptureResult(result, request);
192e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    }
193e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                });
194e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            }
195feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
1964aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        return mCurrentError == NO_CAPTURE_ERROR;
197feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
198feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
199385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala    public synchronized boolean setCaptureResult(final RequestHolder request,
200385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala            final CameraMetadataNative result) {
201385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala        return setCaptureResult(request, result, NO_CAPTURE_ERROR, /*errorArg*/null);
202385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala    }
203385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala
204feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
2052da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen     * Set repeating request error.
2062da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen     *
2072da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen     * <p>Repeating request has been stopped due to an error such as abandoned output surfaces.</p>
2082da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen     *
2092da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen     * @param lastFrameNumber Frame number of the last repeating request before it is stopped.
2102da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen     */
2112da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen    public synchronized void setRepeatingRequestError(final long lastFrameNumber) {
2122da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen        mCurrentHandler.post(new Runnable() {
2132da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen            @Override
2142da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen            public void run() {
2152da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen                mCurrentListener.onRepeatingRequestError(lastFrameNumber);
2162da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen            }
2172da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen        });
2182da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen    }
2192da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen
2202da496f1ce63548486fe28e074f6af90c970db8cChien-Yu Chen    /**
221feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Set the listener for state transition callbacks.
222feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
223feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param handler handler on which to call the callbacks.
224feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param listener the {@link CameraDeviceStateListener} callbacks to call.
225feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
226feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public synchronized void setCameraDeviceCallbacks(Handler handler,
227feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                                                      CameraDeviceStateListener listener) {
228feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCurrentHandler = handler;
229feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCurrentListener = listener;
230feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
231feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
232feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private void doStateTransition(int newState) {
2334aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk        doStateTransition(newState, /*timestamp*/0, NO_CAPTURE_ERROR);
23491838ded36131525312739c0929913b215519c2aRuben Brunk    }
23591838ded36131525312739c0929913b215519c2aRuben Brunk
236e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    private void doStateTransition(int newState, final long timestamp, final int error) {
237e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (newState != mCurrentState) {
238e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            String stateName = "UNKNOWN";
239e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            if (newState >= 0 && newState < sStateNames.length) {
240e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                stateName = sStateNames[newState];
241feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
242e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.i(TAG, "Legacy camera service transitioning to state " + stateName);
243feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
24451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
24551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        // If we transitioned into a non-IDLE/non-ERROR state then mark the device as busy
24651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        if(newState != STATE_ERROR && newState != STATE_IDLE) {
24751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            if (mCurrentState != newState && mCurrentHandler != null &&
24851dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    mCurrentListener != null) {
24951dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                mCurrentHandler.post(new Runnable() {
25051dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    @Override
25151dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    public void run() {
25251dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                        mCurrentListener.onBusy();
25351dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                    }
25451dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin                });
25551dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin            }
25651dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin        }
25751dcfd65a6742884e07182dd7d13b916fd4e0305Igor Murashkin
258feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        switch(newState) {
259feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            case STATE_ERROR:
260feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentState != STATE_ERROR && mCurrentHandler != null &&
261feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        mCurrentListener != null) {
262feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    mCurrentHandler.post(new Runnable() {
263feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        @Override
264feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        public void run() {
265385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala                            mCurrentListener.onError(mCurrentError, /*errorArg*/null, mCurrentRequest);
266feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        }
267feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    });
268feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
269feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                mCurrentState = STATE_ERROR;
270feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                break;
271feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            case STATE_CONFIGURING:
272feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentState != STATE_UNCONFIGURED && mCurrentState != STATE_IDLE) {
273feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    Log.e(TAG, "Cannot call configure while in state: " + mCurrentState);
2744aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
275feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    doStateTransition(STATE_ERROR);
276feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    break;
277feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
278feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentState != STATE_CONFIGURING && mCurrentHandler != null &&
279feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        mCurrentListener != null) {
280feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    mCurrentHandler.post(new Runnable() {
281feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        @Override
282feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        public void run() {
283feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                            mCurrentListener.onConfiguring();
284feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        }
285feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    });
286feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
287feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                mCurrentState = STATE_CONFIGURING;
288feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                break;
289feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            case STATE_IDLE:
290d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                if (mCurrentState == STATE_IDLE) {
291d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                    break;
292d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk                }
293d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk
294feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentState != STATE_CONFIGURING && mCurrentState != STATE_CAPTURING) {
295feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    Log.e(TAG, "Cannot call idle while in state: " + mCurrentState);
2964aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
297feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    doStateTransition(STATE_ERROR);
298feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    break;
299feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
300d85e1a6ced452c9bd0d805f6ce19f50c9ea9b0a6Ruben Brunk
301feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentState != STATE_IDLE && mCurrentHandler != null &&
302feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        mCurrentListener != null) {
303feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    mCurrentHandler.post(new Runnable() {
304feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        @Override
305feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        public void run() {
306feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                            mCurrentListener.onIdle();
307feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                        }
308feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    });
309feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
310feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                mCurrentState = STATE_IDLE;
311feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                break;
312feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            case STATE_CAPTURING:
313feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentState != STATE_IDLE && mCurrentState != STATE_CAPTURING) {
314feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    Log.e(TAG, "Cannot call capture while in state: " + mCurrentState);
3154aed87a9ed31a1ea7fd1ac8fd9ae538d9ecbef7eRuben Brunk                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
316feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    doStateTransition(STATE_ERROR);
317feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    break;
318feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
319e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
320feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                if (mCurrentHandler != null && mCurrentListener != null) {
321e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    if (error != NO_CAPTURE_ERROR) {
322e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        mCurrentHandler.post(new Runnable() {
323e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            @Override
324e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            public void run() {
325385f9e2146d2600ae9fd20053aab8ee5abcac9a6Eino-Ville Talvala                                mCurrentListener.onError(error, /*errorArg*/null, mCurrentRequest);
326e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            }
327e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        });
328e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    } else {
329e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        mCurrentHandler.post(new Runnable() {
330e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            @Override
331e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            public void run() {
332e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                                mCurrentListener.onCaptureStarted(mCurrentRequest, timestamp);
333e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                            }
334e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                        });
335e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk                    }
336feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                }
337feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                mCurrentState = STATE_CAPTURING;
338feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                break;
339feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            default:
340feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                throw new IllegalStateException("Transition to unknown state: " + newState);
341feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
342feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
343feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
344feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
345feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
346