AndroidCameraAgentImpl.java revision 7e6c76ef7faf26aa1060b4abc1c65934b4e45338
1bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/*
2bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * Copyright (C) 2013 The Android Open Source Project
3bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong *
4bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * Licensed under the Apache License, Version 2.0 (the "License");
5bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * you may not use this file except in compliance with the License.
6bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * You may obtain a copy of the License at
7bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong *
8bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong *      http://www.apache.org/licenses/LICENSE-2.0
9bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong *
10bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * Unless required by applicable law or agreed to in writing, software
11bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * distributed under the License is distributed on an "AS IS" BASIS,
12bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * See the License for the specific language governing permissions and
14bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * limitations under the License.
15bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong */
16bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
17bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongpackage com.android.ex.camera2.portability;
18bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
19bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.annotation.TargetApi;
20bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.graphics.SurfaceTexture;
21bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera;
22bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.AutoFocusCallback;
23bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.AutoFocusMoveCallback;
24bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.ErrorCallback;
25bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.FaceDetectionListener;
26bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.OnZoomChangeListener;
27bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.Parameters;
28bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.PictureCallback;
29bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.PreviewCallback;
30bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.hardware.Camera.ShutterCallback;
31bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.Build;
32bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.Handler;
33bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.HandlerThread;
34bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.Looper;
35bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.Message;
36bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.os.SystemClock;
37bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport android.view.SurfaceHolder;
38bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
39bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport com.android.ex.camera2.portability.debug.Log;
40bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
41bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport java.io.IOException;
42bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport java.util.LinkedList;
43bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport java.util.Queue;
44bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
45bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/**
46bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * A class to implement {@link CameraManager} of the Android camera framework.
47bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong */
48bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongclass AndroidCameraManagerImpl implements CameraManager {
49bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final Log.Tag TAG = new Log.Tag("AndroidCamMgrImpl");
50bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final long CAMERA_OPERATION_TIMEOUT_MS = 2500;
51bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final long MAX_MESSAGE_QUEUE_LENGTH = 256;
52b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong    private static final int MAX_HISTORY_SIZE = 400;
53bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
54bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Parameters mParameters;
55bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private boolean mParametersIsDirty;
56bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
57bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /* Messages used in CameraHandler. */
58bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Camera initialization/finalization
59bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int OPEN_CAMERA = 1;
60bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int RELEASE =     2;
61bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int RECONNECT =   3;
62bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int UNLOCK =      4;
63bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int LOCK =        5;
64bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Preview
65bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_PREVIEW_TEXTURE_ASYNC =        101;
66bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int START_PREVIEW_ASYNC =              102;
67bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int STOP_PREVIEW =                     103;
68bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_PREVIEW_CALLBACK_WITH_BUFFER = 104;
69bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int ADD_CALLBACK_BUFFER =              105;
70bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_PREVIEW_DISPLAY_ASYNC =        106;
71bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_PREVIEW_CALLBACK =             107;
72bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_ONE_SHOT_PREVIEW_CALLBACK =    108;
73bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Parameters
74bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_PARAMETERS =     201;
75bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int GET_PARAMETERS =     202;
76bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int REFRESH_PARAMETERS = 203;
77bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Focus, Zoom
78bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int AUTO_FOCUS =                   301;
79bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CANCEL_AUTO_FOCUS =            302;
80bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_AUTO_FOCUS_MOVE_CALLBACK = 303;
81bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_ZOOM_CHANGE_LISTENER =     304;
82bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Face detection
83bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_FACE_DETECTION_LISTENER = 461;
84bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int START_FACE_DETECTION =        462;
85bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int STOP_FACE_DETECTION =         463;
86bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_ERROR_CALLBACK =          464;
87bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Presentation
88bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int ENABLE_SHUTTER_SOUND =    501;
89bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int SET_DISPLAY_ORIENTATION = 502;
90bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Capture
91bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CAPTURE_PHOTO = 601;
92bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
93bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /** Camera states **/
94bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // These states are defined bitwise so we can easily to specify a set of
95bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // states together.
96bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CAMERA_UNOPENED = 1;
97bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CAMERA_IDLE = 1 << 1;
98bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CAMERA_UNLOCKED = 1 << 2;
99bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CAMERA_CAPTURING = 1 << 3;
100bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final int CAMERA_FOCUSING = 1 << 4;
101bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
102bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraHandler mCameraHandler;
103bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final HandlerThread mCameraHandlerThread;
104bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraStateHolder mCameraState;
105bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final DispatchThread mDispatchThread;
106bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
107bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Used to retain a copy of Parameters for setting parameters.
108bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Parameters mParamsToSet;
109bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
110bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Handler mCameraExceptionCallbackHandler;
111bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private CameraExceptionCallback mCameraExceptionCallback =
112bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        new CameraExceptionCallback() {
113bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
114bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void onCameraException(RuntimeException e) {
115bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
116bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
117bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        };
118bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
119bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    AndroidCameraManagerImpl() {
120bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread = new HandlerThread("Camera Handler Thread");
121bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread.start();
122bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandler = new CameraHandler(mCameraHandlerThread.getLooper());
123bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraExceptionCallbackHandler = mCameraHandler;
124bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraState = new CameraStateHolder();
125bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread = new DispatchThread();
126bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.start();
127bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
128bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
129bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
130bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback,
131bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            Handler handler) {
132bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        synchronized (mCameraExceptionCallback) {
133bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallback = callback;
134bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallbackHandler = handler;
135bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
136bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
137bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
13860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
139bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void recycle() {
14060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        closeCamera(null, true);
141bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.end();
142bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    @Override
1457e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    public CameraDeviceInfo getCameraDeviceInfo() {
1467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        return AndroidCameraDeviceInfo.create();
1477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
1487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    private static class AndroidCameraDeviceInfo implements CameraDeviceInfo {
1507e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final Camera.CameraInfo[] mCameraInfos;
1517e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mNumberOfCameras;
1527e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstBackCameraId;
1537e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstFrontCameraId;
1547e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1557e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private AndroidCameraDeviceInfo(Camera.CameraInfo[] info, int numberOfCameras,
1567e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                int firstBackCameraId, int firstFrontCameraId) {
1577e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1587e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mCameraInfos = info;
1597e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mNumberOfCameras = numberOfCameras;
1607e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstBackCameraId = firstBackCameraId;
1617e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstFrontCameraId = firstFrontCameraId;
1627e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1637e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1647e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public static AndroidCameraDeviceInfo create() {
1657e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int numberOfCameras;
1667e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            Camera.CameraInfo[] cameraInfos;
1677e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            try {
1687e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                numberOfCameras = Camera.getNumberOfCameras();
1697e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                cameraInfos = new Camera.CameraInfo[numberOfCameras];
1707e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                for (int i = 0; i < numberOfCameras; i++) {
1717e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    cameraInfos[i] = new Camera.CameraInfo();
1727e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    Camera.getCameraInfo(i, cameraInfos[i]);
1737e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1747e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            } catch (RuntimeException ex) {
1757e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                return null;
1767e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1777e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1787e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstFront = NO_DEVICE;
1797e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstBack = NO_DEVICE;
1807e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            // Get the first (smallest) back and first front camera id.
1817e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            for (int i = numberOfCameras - 1; i >= 0; i--) {
1827e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
1837e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    firstBack = i;
1847e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                } else {
1857e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
1867e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                        firstFront = i;
1877e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    }
1887e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1897e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1907e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1917e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return new AndroidCameraDeviceInfo(cameraInfos, numberOfCameras, firstBack, firstFront);
1927e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1937e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1947e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1957e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public Camera.CameraInfo[] getCameraInfos() {
1967e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mCameraInfos;
1977e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1987e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1997e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
2007e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getNumberOfCameras() {
2017e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mNumberOfCameras;
2027e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
2037e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
2047e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
2057e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstBackCameraId() {
2067e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstBackCameraId;
2077e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
2087e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
2097e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
2107e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstFrontCameraId() {
2117e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstFrontCameraId;
2127e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
2137e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class CameraStateHolder {
216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private int mState;
217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public CameraStateHolder() {
219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            setState(CAMERA_UNOPENED);
220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public CameraStateHolder(int state) {
223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            setState(state);
224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public synchronized void setState(int state) {
227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mState = state;
228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            this.notifyAll();
229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public synchronized int getState() {
232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mState;
233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private interface ConditionChecker {
236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            /**
237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong             * @return Whether the condition holds.
238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong             */
239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            boolean success();
240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * A helper method used by {@link #waitToAvoidStates(int)} and
244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * {@link #waitForStates(int)}. This method will wait until the
245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * condition is successful.
246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param stateChecker The state checker to be used.
248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param timeoutMs The timeout limit in milliseconds.
249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return {@code false} if the wait is interrupted or timeout limit is
250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         reached.
251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private boolean waitForCondition(ConditionChecker stateChecker,
253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                long timeoutMs) {
254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            long timeBound = SystemClock.uptimeMillis() + timeoutMs;
255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            synchronized (this) {
256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                while (!stateChecker.success()) {
257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        this.wait(timeoutMs);
259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } catch (InterruptedException ex) {
260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (SystemClock.uptimeMillis() > timeBound) {
261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            // Timeout.
262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            Log.w(TAG, "Timeout waiting.");
263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        return false;
265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return true;
269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Block the current thread until the state becomes one of the
273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * specified.
274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param states Expected states.
276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return {@code false} if the wait is interrupted or timeout limit is
277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         reached.
278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public boolean waitForStates(final int states) {
280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return waitForCondition(new ConditionChecker() {
281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public boolean success() {
283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    return (states | mState) == states;
284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, CAMERA_OPERATION_TIMEOUT_MS);
286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
287bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
288bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
289bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Block the current thread until the state becomes NOT one of the
290bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * specified.
291bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
292bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param states States to avoid.
293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return {@code false} if the wait is interrupted or timeout limit is
294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         reached.
295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public boolean waitToAvoidStates(final int states) {
297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return waitForCondition(new ConditionChecker() {
298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public boolean success() {
300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    return (states & mState) == 0;
301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, CAMERA_OPERATION_TIMEOUT_MS);
303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
307bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * The handler on which the actual camera operations happen.
308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private class CameraHandler extends Handler {
310b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong
311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private Camera mCamera;
31260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        private int mCameraId;
313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
314742beb4e81cfcdfa9d4f7d3252be7be797a1e462Sascha Haeberling        private final LinkedList<Integer> mMsgHistory;
315b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong
316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private class CaptureCallbacks {
317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final ShutterCallback mShutter;
318bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mRaw;
319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mPostView;
320bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mJpeg;
321bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
322bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            CaptureCallbacks(ShutterCallback shutter, PictureCallback raw, PictureCallback postView,
323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    PictureCallback jpeg) {
324bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mShutter = shutter;
325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mRaw = raw;
326bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mPostView = postView;
327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJpeg = jpeg;
328bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
330bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        CameraHandler(Looper looper) {
332bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            super(looper);
333b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            mMsgHistory = new LinkedList<Integer>();
334b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            // We add a -1 at the beginning to mark the very beginning of the
335b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            // history.
336b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            mMsgHistory.offerLast(-1);
337b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong        }
338b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong
339b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong        private String generateHistoryString(int cameraId) {
340b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            String info = new String("HIST");
341b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            info += "_ID" + cameraId;
342b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            for (Integer msg : mMsgHistory) {
343b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                info = info + '_' + msg.toString();
344b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            }
345b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            info += "_HEND";
346b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            return info;
347bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void startFaceDetection() {
350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.startFaceDetection();
351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void stopFaceDetection() {
354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.stopFaceDetection();
355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
356bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
357bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setFaceDetectionListener(FaceDetectionListener listener) {
358bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.setFaceDetectionListener(listener);
359bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
360bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
361bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setPreviewTexture(Object surfaceTexture) {
362bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
363bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
364bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (IOException e) {
365bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "Could not set preview texture", e);
366bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
368bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
369bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
370bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void enableShutterSound(boolean enable) {
371bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.enableShutterSound(enable);
372bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
374bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
375bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setAutoFocusMoveCallback(
376bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                android.hardware.Camera camera, Object cb) {
377bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
378bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException ex) {
380bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.w(TAG, ex.getMessage());
381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
382bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
383bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
384bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void capture(final CaptureCallbacks cb) {
385bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
386bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.takePicture(cb.mShutter, cb.mRaw, cb.mPostView, cb.mJpeg);
387bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException e) {
388bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                // TODO: output camera state and focus state for debugging.
389bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "take picture failed.");
390bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
391bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
392bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
393bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
394bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void requestTakePicture(
395bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final ShutterCallback shutter,
396bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback raw,
397bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback postView,
398bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback jpeg) {
399bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final CaptureCallbacks callbacks = new CaptureCallbacks(shutter, raw, postView, jpeg);
400bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            obtainMessage(CAPTURE_PHOTO, callbacks).sendToTarget();
401bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
402bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
403bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
404bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * This method does not deal with the API level check.  Everyone should
405bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * check first for supported operations before sending message to this handler.
406bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
407bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
408bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void handleMessage(final Message msg) {
409b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            mMsgHistory.offerLast(msg.what);
410b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            while (mMsgHistory.size() > MAX_HISTORY_SIZE) {
411b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                mMsgHistory.pollFirst();
412b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong            }
413bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                switch (msg.what) {
415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case OPEN_CAMERA: {
416bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
418bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mCameraState.getState() != CAMERA_UNOPENED) {
41960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
420bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
421bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
422bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
423bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera = android.hardware.Camera.open(cameraId);
424bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mCamera != null) {
42560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCameraId = cameraId;
426bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParametersIsDirty = true;
427bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
428bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            // Get a instance of Camera.Parameters for later use.
429742beb4e81cfcdfa9d4f7d3252be7be797a1e462Sascha Haeberling                            mParamsToSet = mCamera.getParameters();
430bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
431bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCameraState.setState(CAMERA_IDLE);
432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                openCallback.onCameraOpened(
434c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                        new AndroidCameraProxyImpl(cameraId, mCamera,
435c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                                new AndroidCameraCapabilities(mParamsToSet))
436c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                );
437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
438bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
439bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
440b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
441bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
442bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
443bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
444bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
445bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
446bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case RELEASE: {
44760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        if (mCamera != null) {
44860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera.release();
44960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCameraState.setState(CAMERA_UNOPENED);
45060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera = null;
45160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        } else {
45260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            Log.w(TAG, "Releasing camera without any camera opened.");
45360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        }
454bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
455bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
456bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
457bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case RECONNECT: {
458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallbackForward cbForward =
459bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                (CameraOpenCallbackForward) msg.obj;
460bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
461bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
462bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.reconnect();
463bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException ex) {
464bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (cbForward != null) {
46560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                cbForward.onReconnectionFailure(AndroidCameraManagerImpl.this,
46660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                        generateHistoryString(mCameraId));
467bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
468bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
469bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
470bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
471bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_IDLE);
472bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
473c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                            cbForward.onCameraOpened(new AndroidCameraProxyImpl(cameraId, mCamera,
474c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                    new AndroidCameraCapabilities(mParamsToSet)));
475bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
476bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
477bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
478bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
479bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case UNLOCK: {
480bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.unlock();
481bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_UNLOCKED);
482bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
483bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
484bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
485bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case LOCK: {
486bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.lock();
487bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_IDLE);
488bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
489bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
490bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
491bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_PREVIEW_TEXTURE_ASYNC: {
492bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setPreviewTexture(msg.obj);
493bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
494bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
495bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
496bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_PREVIEW_DISPLAY_ASYNC: {
497bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
498bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
499bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException e) {
500bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            throw new RuntimeException(e);
501bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
502bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
503bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
504bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
505bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case START_PREVIEW_ASYNC: {
506bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraStartPreviewCallbackForward cbForward =
507bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            (CameraStartPreviewCallbackForward) msg.obj;
508bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.startPreview();
509bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
510bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cbForward.onPreviewStarted();
511bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
512bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
513bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
514bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
515bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case STOP_PREVIEW: {
516bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.stopPreview();
517bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
518bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
519bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
520bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_PREVIEW_CALLBACK_WITH_BUFFER: {
521bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallbackWithBuffer((PreviewCallback) msg.obj);
522bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
523bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
524bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
525bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_ONE_SHOT_PREVIEW_CALLBACK: {
526bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setOneShotPreviewCallback((PreviewCallback) msg.obj);
527bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
528bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
529bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
530bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case ADD_CALLBACK_BUFFER: {
531bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.addCallbackBuffer((byte[]) msg.obj);
532bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
533bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
534bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
535bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case AUTO_FOCUS: {
536bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_FOCUSING);
537bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.autoFocus((AutoFocusCallback) msg.obj);
538bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
539bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
540bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
541bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case CANCEL_AUTO_FOCUS: {
542bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.cancelAutoFocus();
543bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_IDLE);
544bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
545bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
546bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
547bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_AUTO_FOCUS_MOVE_CALLBACK: {
548bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setAutoFocusMoveCallback(mCamera, msg.obj);
549bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
550bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
551bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
552bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_DISPLAY_ORIENTATION: {
553bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setDisplayOrientation(msg.arg1);
554bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
555bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
556bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
557bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_ZOOM_CHANGE_LISTENER: {
558bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setZoomChangeListener((OnZoomChangeListener) msg.obj);
559bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
560bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
561bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
562bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_FACE_DETECTION_LISTENER: {
563bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setFaceDetectionListener((FaceDetectionListener) msg.obj);
564bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
565bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
566bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
567bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case START_FACE_DETECTION: {
568bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        startFaceDetection();
569bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
570bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
571bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
572bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case STOP_FACE_DETECTION: {
573bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        stopFaceDetection();
574bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
575bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
576bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_ERROR_CALLBACK: {
578bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setErrorCallback((ErrorCallback) msg.obj);
579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
580bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
581bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
582bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_PARAMETERS: {
583bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParametersIsDirty = true;
584bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParamsToSet.unflatten((String) msg.obj);
585bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setParameters(mParamsToSet);
586bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
587bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
588bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
589bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case GET_PARAMETERS: {
590bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mParametersIsDirty) {
591bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParameters = mCamera.getParameters();
592bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParametersIsDirty = false;
593bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
594bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
595bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
596bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
597bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case SET_PREVIEW_CALLBACK: {
598bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallback((PreviewCallback) msg.obj);
599bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
600bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
601bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
602bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case ENABLE_SHUTTER_SOUND: {
603bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        enableShutterSound((msg.arg1 == 1) ? true : false);
604bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
605bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
606bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
607bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case REFRESH_PARAMETERS: {
608bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParametersIsDirty = true;
609bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
610bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
611bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
612bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    case CAPTURE_PHOTO: {
613bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_CAPTURING);
614bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        capture((CaptureCallbacks) msg.obj);
615bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
616bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
617bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
618bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    default: {
619bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
620bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
621bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
622bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (final RuntimeException e) {
623bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                if (msg.what != RELEASE && mCamera != null) {
624bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
625bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.release();
626bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_UNOPENED);
627bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } catch (Exception ex) {
628bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.e(TAG, "Fail to release the camera.");
629bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
630bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCamera = null;
631bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                } else {
632bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (mCamera == null) {
633bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (msg.what == OPEN_CAMERA) {
634b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                            final int cameraId = msg.arg1;
635bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (msg.obj != null) {
636b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(
637b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                        msg.arg1, generateHistoryString(cameraId));
638bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
639bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
640bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null.");
641bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
642bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        return;
643bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
644bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
645bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                synchronized (mCameraExceptionCallback) {
646bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraExceptionCallbackHandler.post(new Runnable() {
647bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
648bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
649bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                mCameraExceptionCallback.onCameraException(e);
650bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
651bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        });
652bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
653bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
654bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
655bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
656bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
657bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private class DispatchThread extends Thread {
658bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
659bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Queue<Runnable> mJobQueue;
660bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private Boolean mIsEnded;
661bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
662bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public DispatchThread() {
663bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            super("Camera Job Dispatch Thread");
664bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mJobQueue = new LinkedList<Runnable>();
665bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mIsEnded = new Boolean(false);
666bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
667bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
668bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
669bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Queues up the job.
670bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
671bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param job The job to run.
672bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
673bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void runJob(Runnable job) {
674bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (isEnded()) {
675bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw new IllegalStateException(
676bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        "Trying to run job on interrupted dispatcher thread");
677bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
678bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            synchronized (mJobQueue) {
679bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                if (mJobQueue.size() == MAX_MESSAGE_QUEUE_LENGTH) {
680bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    throw new RuntimeException("Camera master thread job queue full");
681bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
682bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
683bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJobQueue.add(job);
684bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJobQueue.notifyAll();
685bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
686bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
687bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
688bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
689bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Queues up the job and wait for it to be done.
690bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
691bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param job The job to run.
692bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param timeoutMs Timeout limit in milliseconds.
693bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param jobMsg The message to log when the job runs timeout.
694bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return Whether the job finishes before timeout.
695bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
696bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public boolean runJobSync(final Runnable job, Object waitLock, long timeoutMs, String jobMsg) {
697bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            synchronized (waitLock) {
698bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                long timeoutBound = SystemClock.uptimeMillis() + timeoutMs;
699bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                try {
700bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    runJob(job);
701bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    waitLock.wait();
702bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                } catch (InterruptedException ex) {
70360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    Log.w(TAG, "Job interrupted");
704bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (SystemClock.uptimeMillis() > timeoutBound) {
705bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        // Timeout.
706bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.w(TAG, "Timeout waiting camera operation:" + jobMsg);
707bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
708bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    return false;
709bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
710bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
711bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return true;
712bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
713bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
714bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
715bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Gracefully ends this thread. Will stop after all jobs are processed.
716bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
717bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void end() {
718bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            synchronized (mIsEnded) {
719bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mIsEnded = true;
720bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
721bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            synchronized(mJobQueue) {
722bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJobQueue.notifyAll();
723bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
724bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
725bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
726bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private boolean isEnded() {
727bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            synchronized (mIsEnded) {
728bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return mIsEnded;
729bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
730bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
731bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
732bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
733bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void run() {
734bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            while(true) {
735bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Runnable job = null;
736bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                synchronized (mJobQueue) {
737bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    while (mJobQueue.size() == 0 && !isEnded()) {
738bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
739bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mJobQueue.wait();
740bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (InterruptedException ex) {
74160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            Log.w(TAG, "Dispatcher thread wait() interrupted, exiting");
742bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
743bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
744bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
745bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
746bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    job = mJobQueue.poll();
747bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
748bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
749bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                if (job == null) {
750bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    // mJobQueue.poll() returning null means wait() is
751bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    // interrupted and the queue is empty.
752bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (isEnded()) {
753bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
754bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
755bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    continue;
756bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
757bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
758bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                job.run();
759bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
760bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                synchronized (DispatchThread.this) {
761bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(new Runnable() {
762bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
763bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
764bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            synchronized (DispatchThread.this) {
765bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                DispatchThread.this.notifyAll();
766bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
767bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
768bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
769bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
770bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        DispatchThread.this.wait();
771bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } catch (InterruptedException ex) {
772bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        // TODO: do something here.
773bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
774bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
775bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
776bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraHandlerThread.quitSafely();
777bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
778bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
779bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
780bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
78160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    public void openCamera(final Handler handler, final int cameraId,
78260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                           final CameraOpenCallback callback) {
783bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.runJob(new Runnable() {
784bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
785bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void run() {
786bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
787bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
788bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
789bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        });
790bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
791bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
79260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
79360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    public void closeCamera(CameraProxy camera, boolean synced) {
79460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        if (synced) {
79560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
79660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
79760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            mDispatchThread.runJobSync(new Runnable() {
79860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                @Override
79960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                public void run() {
80060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.obtainMessage(RELEASE).sendToTarget();
80160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
80260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                }
80360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera release");
80460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        } else {
80560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            mDispatchThread.runJob(new Runnable() {
80660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                @Override
80760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                public void run() {
80860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.removeCallbacksAndMessages(null);
80960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.obtainMessage(RELEASE).sendToTarget();
81060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                }
81160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            });
81260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        }
81360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    }
81460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
815bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
816bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A class which implements {@link CameraManager.CameraProxy} and
817bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera handler thread.
818bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
819bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
820bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final int mCameraId;
821bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /* TODO: remove this Camera instance. */
822bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Camera mCamera;
823c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private final AndroidCameraCapabilities mCapabilities;
824bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
825c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private AndroidCameraProxyImpl(int cameraId, Camera camera,
826c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                AndroidCameraCapabilities capabilities) {
827bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
828bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraId = cameraId;
829c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            mCapabilities = capabilities;
830bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
831bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
832bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
833bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public android.hardware.Camera getCamera() {
834bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCamera;
835bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
836bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
837bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
838bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public int getCameraId() {
839bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCameraId;
840bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
841bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
842bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
843c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        public CameraCapabilities getCapabilities() {
844c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            return new AndroidCameraCapabilities(mCapabilities);
845c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        }
846c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong
847c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        @Override
848bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void reconnect(final Handler handler, final CameraOpenCallback cb) {
849bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
850bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
851bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
852bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(RECONNECT, mCameraId, 0,
853bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget();
854bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
855bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
856bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
857bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
858bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
859bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void unlock() {
860bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
861bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
862bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
863bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
864bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(UNLOCK);
865bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
866bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
867bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera unlock");
868bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
869bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
870bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
871bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void lock() {
872bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
873bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
874bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
875bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(LOCK);
876bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
877bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
878bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
879bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
880bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
881bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewTexture(final SurfaceTexture surfaceTexture) {
882bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
883bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
884bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
885bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
886bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
887bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
888bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
889bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
890bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
891bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
892bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) {
893bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
894bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
895bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
896bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
897bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
898bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
899bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
900bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
901bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "set preview texture");
902bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
903bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
904bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
905bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDisplay(final SurfaceHolder surfaceHolder) {
906bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
907bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
908bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
909bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder)
910bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
911bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
912bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
913bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
914bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
915bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
916bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startPreview() {
917bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
918bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
919bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
920bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(START_PREVIEW_ASYNC, null).sendToTarget();
921bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
922bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
923bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
924bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
925bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
926bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startPreviewWithCallback(final Handler handler,
927bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraStartPreviewCallback cb) {
928bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
929bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
930bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
931bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(START_PREVIEW_ASYNC,
932bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        CameraStartPreviewCallbackForward.getNewInstance(handler, cb)).sendToTarget();
933bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
934bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
935bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
936bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
937bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
938bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void stopPreview() {
939bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
940bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
941bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
942bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
943bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(STOP_PREVIEW);
944bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
945bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
946bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "stop preview");
947bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
948bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
949bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
950bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallback(
951bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
952bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
953bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
954bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
955bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_PREVIEW_CALLBACK, PreviewCallbackForward
956bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
957bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
958bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
959bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
960bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
961bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
962bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setOneShotPreviewCallback(final Handler handler,
963bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPreviewDataCallback cb) {
964bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
965bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
966bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
967bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_ONE_SHOT_PREVIEW_CALLBACK,
968bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
969bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
970bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
971bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
972bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
973bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
974bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
975bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
976bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallbackWithBuffer(
977bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
978bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
979bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
980bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
981bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_PREVIEW_CALLBACK_WITH_BUFFER,
982bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
983bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
984bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
985bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
986bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
987bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
988bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
989bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
990bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void addCallbackBuffer(final byte[] callbackBuffer) {
991bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
992bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
993bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
994bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(ADD_CALLBACK_BUFFER, callbackBuffer)
995bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
996bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
997bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
998bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
999bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1000bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1001bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void autoFocus(final Handler handler, final CameraAFCallback cb) {
1002bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final AutoFocusCallback afCallback = new AutoFocusCallback() {
1003bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1004bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onAutoFocus(final boolean b, Camera camera) {
1005bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (mCameraState.getState() != CAMERA_FOCUSING) {
1006bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.w(TAG, "onAutoFocus callback returning when not focusing");
1007bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
1008bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_IDLE);
1009bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
1010bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
1011bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
1012bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
1013bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cb.onAutoFocus(b, AndroidCameraProxyImpl.this);
1014bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
1015bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
1016bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1017bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
1018bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1019bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1020bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1021bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraState.waitForStates(CAMERA_IDLE);
1022bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(AUTO_FOCUS, afCallback).sendToTarget();
1023bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1024bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1025bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1026bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1027bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1028bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void cancelAutoFocus() {
1029bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1030bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1031bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1032bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.removeMessages(AUTO_FOCUS);
1033bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(CANCEL_AUTO_FOCUS);
1034bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1035bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1036bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1037bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1038bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1039bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1040bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setAutoFocusMoveCallback(
1041bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraAFMoveCallback cb) {
1042bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1043bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1044bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1045bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_AUTO_FOCUS_MOVE_CALLBACK, AFMoveCallbackForward
1046bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
1047bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
1048bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1049bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1050bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1051bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1052bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1053bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void takePicture(
1054bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraShutterCallback shutter,
1055bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback raw, final CameraPictureCallback post,
1056bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback jpeg) {
1057bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final PictureCallback jpegCallback = new PictureCallback() {
1058bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1059bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onPictureTaken(final byte[] data, Camera camera) {
1060bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (mCameraState.getState() != CAMERA_CAPTURING) {
106160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        Log.w(TAG, "picture callback returning when not capturing");
1062bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
1063bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCameraState.setState(CAMERA_IDLE);
1064bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
1065bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
1066bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
1067bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
1068bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpeg.onPictureTaken(data, AndroidCameraProxyImpl.this);
1069bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
1070bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
1071bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1072bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
1073bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1074bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1075bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1076bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1077d3865a20b022f6d54fe7ac052768a7ff0710017fDoris Liu                    mCameraState.waitForStates(CAMERA_IDLE | CAMERA_UNLOCKED);
1078bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.requestTakePicture(ShutterCallbackForward
1079bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .getNewInstance(handler, AndroidCameraProxyImpl.this, shutter),
1080bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
1081bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, raw),
1082bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
1083bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, post),
1084bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpegCallback);
1085bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1086bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1087bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1088bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1089bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1090bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setDisplayOrientation(final int degrees) {
1091bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1092bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1093bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1094bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_DISPLAY_ORIENTATION, degrees, 0)
1095bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
1096bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1097bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1098bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1099bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1100bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1101bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setZoomChangeListener(final OnZoomChangeListener listener) {
1102bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1103bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1104bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1105bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_ZOOM_CHANGE_LISTENER, listener).sendToTarget();
1106bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1107bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1108bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1109bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1110bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1111bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setFaceDetectionCallback(final Handler handler,
1112bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraFaceDetectionCallback cb) {
1113bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1114bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1115bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1116bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_FACE_DETECTION_LISTENER,
1117bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            FaceDetectionCallbackForward
1118bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
1119bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
1120bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1121bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1122bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1123bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1124bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1125bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startFaceDetection() {
1126bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1127bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1128bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1129bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(START_FACE_DETECTION);
1130bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1131bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1132bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1133bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1134bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1135bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void stopFaceDetection() {
1136bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1137bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1138bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1139bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(STOP_FACE_DETECTION);
1140bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1141bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1142bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1143bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1144bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1145bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setErrorCallback(final Handler handler, final CameraErrorCallback cb) {
1146bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1147bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1148bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1149bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_ERROR_CALLBACK, ErrorCallbackForward
1150bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb)
1151bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    ).sendToTarget();
1152bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1153bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1154bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1155bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1156bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1157bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setParameters(final Parameters params) {
1158bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (params == null) {
1159bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.v(TAG, "null parameters in setParameters()");
1160bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return;
1161bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final String flattenedParameters = params.flatten();
1163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1164bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1165bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1166bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraState.waitForStates(CAMERA_IDLE | CAMERA_UNLOCKED);
1167bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(SET_PARAMETERS, flattenedParameters).sendToTarget();
1168bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1169bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1170bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Parameters getParameters() {
1174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
1175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
1176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(GET_PARAMETERS);
1179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
1180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "get parameters");
1182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mParameters;
1183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void refreshParameters() {
1187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.sendEmptyMessage(REFRESH_PARAMETERS);
1191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void enableShutterSound(final boolean enable) {
1197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.obtainMessage(ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0)
1201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
1202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class WaitDoneBundle {
1208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Runnable mUnlockRunnable;
1209bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Object mWaitLock;
1210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        WaitDoneBundle() {
1212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mWaitLock = new Object();
1213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mUnlockRunnable = new Runnable() {
1214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    synchronized (mWaitLock) {
1217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mWaitLock.notifyAll();
1218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
1219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
1221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward AutoFocusCallback to another thread.
1226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFCallbackForward implements AutoFocusCallback {
1228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFCallback mCallback;
1231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFCallbackForward getNewInstance(
1242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFCallback cb) {
1243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFCallbackForward(handler, camera, cb);
1247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFCallbackForward(
1250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFCallback cb) {
1251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocus(final boolean b, Camera camera) {
1258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocus(b, mCamera);
1262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ErrorCallback to another thread.
1269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ErrorCallbackForward implements Camera.ErrorCallback {
1271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraErrorCallback mCallback;
1274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ErrorCallbackForward getNewInstance(
1285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraErrorCallback cb) {
1286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1287bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1288bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1289bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ErrorCallbackForward(handler, camera, cb);
1290bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1291bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1292bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ErrorCallbackForward(
1293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraErrorCallback cb) {
1294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onError(final int error, Camera camera) {
1301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onError(error, mCamera);
1305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1307bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1310bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /** A helper class to forward AutoFocusMoveCallback to another thread. */
1311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1312bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
1313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1314bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFMoveCallback mCallback;
1315bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1318bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFMoveCallbackForward}.
1319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1320bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1321bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1322bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFMoveCallbackForward},
1324bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1326bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFMoveCallbackForward getNewInstance(
1327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
1328bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1330bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFMoveCallbackForward(handler, camera, cb);
1332bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFMoveCallbackForward(
1335bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
1336bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1337bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1338bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1339bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1340bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1341bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1342bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocusMoving(
1343bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final boolean moving, android.hardware.Camera camera) {
1344bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1345bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1346bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1347bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocusMoving(moving, mCamera);
1348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ShutterCallback to to another thread.
1355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1356bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ShutterCallbackForward implements ShutterCallback {
1357bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1358bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraShutterCallback mCallback;
1359bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1360bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1361bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1362bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link ShutterCallbackForward}.
1363bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1364bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1365bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1366bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link ShutterCallbackForward},
1368bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1369bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1370bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ShutterCallbackForward getNewInstance(
1371bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraShutterCallback cb) {
1372bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1374bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1375bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ShutterCallbackForward(handler, camera, cb);
1376bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1377bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1378bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ShutterCallbackForward(
1379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraShutterCallback cb) {
1380bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1382bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1383bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1384bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1385bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1386bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onShutter() {
1387bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1388bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1389bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1390bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onShutter(mCamera);
1391bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1392bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1393bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1394bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1395bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1396bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1397bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PictureCallback to another thread.
1398bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1399bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PictureCallbackForward implements PictureCallback {
1400bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1401bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPictureCallback mCallback;
1402bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1403bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1404bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1405bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PictureCallbackForward}.
1406bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1407bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1408bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1409bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1410bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PictureCallbackForward},
1411bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1412bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1413bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PictureCallbackForward getNewInstance(
1414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPictureCallback cb) {
1415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1416bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1418bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PictureCallbackForward(handler, camera, cb);
1419bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1420bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1421bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PictureCallbackForward(
1422bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPictureCallback cb) {
1423bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1424bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1425bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1426bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1427bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1428bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1429bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPictureTaken(
1430bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1431bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1434bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPictureTaken(data, mCamera);
1435bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1436bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1438bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1439bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1440bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1441bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PreviewCallback to another thread.
1442bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1443bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PreviewCallbackForward implements PreviewCallback {
1444bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1445bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPreviewDataCallback mCallback;
1446bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1447bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1448bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1449bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PreviewCallbackForward}.
1450bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1451bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1452bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1453bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1454bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PreviewCallbackForward},
1455bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1456bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1457bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PreviewCallbackForward getNewInstance(
1458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
1459bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1460bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1461bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1462bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PreviewCallbackForward(handler, camera, cb);
1463bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1464bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1465bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PreviewCallbackForward(
1466bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
1467bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1468bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1469bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1470bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1471bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1472bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1473bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewFrame(
1474bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1475bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1476bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1477bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1478bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPreviewFrame(data, mCamera);
1479bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1480bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1481bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1482bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1483bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1484bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class FaceDetectionCallbackForward implements FaceDetectionListener {
1485bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1486bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraFaceDetectionCallback mCallback;
1487bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1488bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1489bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1490bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
1491bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1492bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1493bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1494bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1495bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link FaceDetectionCallbackForward},
1496bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1497bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1498bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static FaceDetectionCallbackForward getNewInstance(
1499bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
1500bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1501bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1502bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1503bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new FaceDetectionCallbackForward(handler, camera, cb);
1504bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1505bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1506bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private FaceDetectionCallbackForward(
1507bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
1508bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1509bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1510bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1511bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1512bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1513bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1514bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onFaceDetection(
1515bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Camera.Face[] faces, Camera camera) {
1516bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1517bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1518bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1519bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onFaceDetection(faces, mCamera);
1520bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1521bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1522bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1523bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1524bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1525bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1526bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A callback helps to invoke the original callback on another
1527bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * {@link android.os.Handler}.
1528bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1529bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class CameraOpenCallbackForward implements CameraOpenCallback {
1530bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1531bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraOpenCallback mCallback;
1532bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1533bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1534bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
1535bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1536bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1537bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb The callback to be invoked.
1538bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return The instance of the {@link FaceDetectionCallbackForward}, or
1539bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *         null if any parameter is null.
1540bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1541bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static CameraOpenCallbackForward getNewInstance(
1542bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraOpenCallback cb) {
1543bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || cb == null) {
1544bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1545bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1546bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new CameraOpenCallbackForward(handler, cb);
1547bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1548bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1549bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private CameraOpenCallbackForward(Handler h, CameraOpenCallback cb) {
1550bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            // Given that we are using the main thread handler, we can create it
1551bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            // here instead of holding onto the PhotoModule objects. In this
1552bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            // way, we can avoid memory leak.
1553bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = new Handler(Looper.getMainLooper());
1554bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1555bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1556bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1557bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1558bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onCameraOpened(final CameraProxy camera) {
1559bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1560bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1561bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1562bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onCameraOpened(camera);
1563bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1564bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1565bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1566bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1567bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1568bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onCameraDisabled(final int cameraId) {
1569bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1570bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1571bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1572bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onCameraDisabled(cameraId);
1573bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1574bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1575bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1576bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1578b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong        public void onDeviceOpenFailure(final int cameraId, final String info) {
1579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1580bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1581bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1582b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                    mCallback.onDeviceOpenFailure(cameraId, info);
1583bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1584bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1585bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1586bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1587bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
158860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        public void onDeviceOpenedAlready(final int cameraId, final String info) {
1589bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1590bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1591bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
159260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCallback.onDeviceOpenedAlready(cameraId, info);
1593bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1594bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1595bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1596bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1597bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
159860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        public void onReconnectionFailure(final CameraManager mgr, final String info) {
1599bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1600bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1601bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
160260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCallback.onReconnectionFailure(mgr, info);
1603bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1604bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1605bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1606bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1607bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1608bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class CameraStartPreviewCallbackForward
1609bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            implements CameraStartPreviewCallback {
1610bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1611bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraStartPreviewCallback mCallback;
1612bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1613bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static CameraStartPreviewCallbackForward getNewInstance(
1614bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraStartPreviewCallback cb) {
1615bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || cb == null) {
1616bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1617bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1618bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new CameraStartPreviewCallbackForward(handler, cb);
1619bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1620bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1621bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private CameraStartPreviewCallbackForward(Handler h,
1622bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                CameraStartPreviewCallback cb) {
1623bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1624bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1625bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1626bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1627bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1628bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewStarted() {
1629bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1630bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1631bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1632bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPreviewStarted();
1633bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1634bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1635bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1636bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1637bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong}
1638