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