AndroidCameraAgentImpl.java revision cef46862d6937bc98bf1a6b087c5daa22b5239f3
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 Kong
44bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/**
45bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * A class to implement {@link CameraManager} of the Android camera framework.
46bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong */
47bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongclass AndroidCameraManagerImpl implements CameraManager {
48bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final Log.Tag TAG = new Log.Tag("AndroidCamMgrImpl");
49bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
50bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Parameters mParameters;
51bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private boolean mParametersIsDirty;
52bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
53bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraHandler mCameraHandler;
54bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final HandlerThread mCameraHandlerThread;
55bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraStateHolder mCameraState;
56bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final DispatchThread mDispatchThread;
57bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
58bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    // Used to retain a copy of Parameters for setting parameters.
59bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Parameters mParamsToSet;
60bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
61bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Handler mCameraExceptionCallbackHandler;
62bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private CameraExceptionCallback mCameraExceptionCallback =
63bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        new CameraExceptionCallback() {
64bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
65bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void onCameraException(RuntimeException e) {
66bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
67bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
68bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        };
69bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
70bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    AndroidCameraManagerImpl() {
71bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread = new HandlerThread("Camera Handler Thread");
72bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread.start();
73bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandler = new CameraHandler(mCameraHandlerThread.getLooper());
74bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraExceptionCallbackHandler = mCameraHandler;
75bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraState = new CameraStateHolder();
76cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread);
77bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.start();
78bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
79bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
80bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
81bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback,
82bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            Handler handler) {
83bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        synchronized (mCameraExceptionCallback) {
84bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallback = callback;
85bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallbackHandler = handler;
86bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
87bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
88bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
8960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
90bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void recycle() {
9160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        closeCamera(null, true);
92bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.end();
93bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
947e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
957e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    @Override
967e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    public CameraDeviceInfo getCameraDeviceInfo() {
977e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        return AndroidCameraDeviceInfo.create();
987e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
997e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1007e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    private static class AndroidCameraDeviceInfo implements CameraDeviceInfo {
1017e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final Camera.CameraInfo[] mCameraInfos;
1027e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mNumberOfCameras;
1037e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstBackCameraId;
1047e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstFrontCameraId;
1057e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1067e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private AndroidCameraDeviceInfo(Camera.CameraInfo[] info, int numberOfCameras,
1077e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                int firstBackCameraId, int firstFrontCameraId) {
1087e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1097e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mCameraInfos = info;
1107e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mNumberOfCameras = numberOfCameras;
1117e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstBackCameraId = firstBackCameraId;
1127e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstFrontCameraId = firstFrontCameraId;
1137e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1147e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1157e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public static AndroidCameraDeviceInfo create() {
1167e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int numberOfCameras;
1177e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            Camera.CameraInfo[] cameraInfos;
1187e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            try {
1197e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                numberOfCameras = Camera.getNumberOfCameras();
1207e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                cameraInfos = new Camera.CameraInfo[numberOfCameras];
1217e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                for (int i = 0; i < numberOfCameras; i++) {
1227e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    cameraInfos[i] = new Camera.CameraInfo();
1237e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    Camera.getCameraInfo(i, cameraInfos[i]);
1247e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1257e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            } catch (RuntimeException ex) {
1267e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                return null;
1277e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1287e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1297e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstFront = NO_DEVICE;
1307e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstBack = NO_DEVICE;
1317e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            // Get the first (smallest) back and first front camera id.
1327e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            for (int i = numberOfCameras - 1; i >= 0; i--) {
1337e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
1347e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    firstBack = i;
1357e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                } else {
1367e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
1377e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                        firstFront = i;
1387e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    }
1397e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1407e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1417e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1427e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return new AndroidCameraDeviceInfo(cameraInfos, numberOfCameras, firstBack, firstFront);
1437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1457e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public Camera.CameraInfo[] getCameraInfos() {
1477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mCameraInfos;
1487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1507e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1517e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getNumberOfCameras() {
1527e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mNumberOfCameras;
1537e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1547e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1557e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1567e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstBackCameraId() {
1577e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstBackCameraId;
1587e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1597e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1607e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1617e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstFrontCameraId() {
1627e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstFrontCameraId;
1637e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1647e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
165bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
166bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
167bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * The handler on which the actual camera operations happen.
168bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
169cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    private class CameraHandler extends HistoryHandler {
170b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong
171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private Camera mCamera;
17260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        private int mCameraId;
173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private class CaptureCallbacks {
175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final ShutterCallback mShutter;
176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mRaw;
177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mPostView;
178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mJpeg;
179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            CaptureCallbacks(ShutterCallback shutter, PictureCallback raw, PictureCallback postView,
181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    PictureCallback jpeg) {
182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mShutter = shutter;
183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mRaw = raw;
184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mPostView = postView;
185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJpeg = jpeg;
186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        CameraHandler(Looper looper) {
190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            super(looper);
191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void startFaceDetection() {
194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.startFaceDetection();
195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void stopFaceDetection() {
198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.stopFaceDetection();
199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setFaceDetectionListener(FaceDetectionListener listener) {
202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.setFaceDetectionListener(listener);
203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setPreviewTexture(Object surfaceTexture) {
206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (IOException e) {
209bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "Could not set preview texture", e);
210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void enableShutterSound(boolean enable) {
215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.enableShutterSound(enable);
216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setAutoFocusMoveCallback(
220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                android.hardware.Camera camera, Object cb) {
221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException ex) {
224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.w(TAG, ex.getMessage());
225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void capture(final CaptureCallbacks cb) {
229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.takePicture(cb.mShutter, cb.mRaw, cb.mPostView, cb.mJpeg);
231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException e) {
232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                // TODO: output camera state and focus state for debugging.
233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "take picture failed.");
234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void requestTakePicture(
239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final ShutterCallback shutter,
240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback raw,
241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback postView,
242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback jpeg) {
243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final CaptureCallbacks callbacks = new CaptureCallbacks(shutter, raw, postView, jpeg);
244cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            obtainMessage(CameraActions.CAPTURE_PHOTO, callbacks).sendToTarget();
245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * This method does not deal with the API level check.  Everyone should
249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * check first for supported operations before sending message to this handler.
250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void handleMessage(final Message msg) {
253cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            super.handleMessage(msg);
254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                switch (msg.what) {
256cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.OPEN_CAMERA: {
257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
259cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        if (mCameraState.getState() != CameraStateHolder.CAMERA_UNOPENED) {
26060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera = android.hardware.Camera.open(cameraId);
265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mCamera != null) {
26660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCameraId = cameraId;
267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParametersIsDirty = true;
268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            // Get a instance of Camera.Parameters for later use.
270742beb4e81cfcdfa9d4f7d3252be7be797a1e462Sascha Haeberling                            mParamsToSet = mCamera.getParameters();
271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
272cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                openCallback.onCameraOpened(
275c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                        new AndroidCameraProxyImpl(cameraId, mCamera,
276c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                                new AndroidCameraCapabilities(mParamsToSet))
277c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                );
278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
281b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
287cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RELEASE: {
28860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        if (mCamera != null) {
28960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera.release();
290cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            mCameraState.setState(CameraStateHolder.CAMERA_UNOPENED);
29160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera = null;
29260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        } else {
29360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            Log.w(TAG, "Releasing camera without any camera opened.");
29460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        }
295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
298cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RECONNECT: {
299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallbackForward cbForward =
300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                (CameraOpenCallbackForward) msg.obj;
301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.reconnect();
304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException ex) {
305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (cbForward != null) {
30660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                cbForward.onReconnectionFailure(AndroidCameraManagerImpl.this,
30760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                        generateHistoryString(mCameraId));
308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
310bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
312cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
314c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                            cbForward.onCameraOpened(new AndroidCameraProxyImpl(cameraId, mCamera,
315c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                    new AndroidCameraCapabilities(mParamsToSet)));
316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
318bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
320cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.UNLOCK: {
321bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.unlock();
322cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_UNLOCKED);
323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
324bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
326cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.LOCK: {
327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.lock();
328cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
330bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
332cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: {
333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setPreviewTexture(msg.obj);
334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
335bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
336bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
337cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: {
338bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
339bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
340bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException e) {
341bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            throw new RuntimeException(e);
342bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
343bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
344bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
345bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
346cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_PREVIEW_ASYNC: {
347bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraStartPreviewCallbackForward cbForward =
348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            (CameraStartPreviewCallbackForward) msg.obj;
349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.startPreview();
350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cbForward.onPreviewStarted();
352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
356cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_PREVIEW: {
357bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.stopPreview();
358bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
359bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
360bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
361cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: {
362bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallbackWithBuffer((PreviewCallback) msg.obj);
363bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
364bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
365bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
366cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: {
367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setOneShotPreviewCallback((PreviewCallback) msg.obj);
368bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
369bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
370bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
371cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ADD_CALLBACK_BUFFER: {
372bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.addCallbackBuffer((byte[]) msg.obj);
373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
374bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
375bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
376cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.AUTO_FOCUS: {
377cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_FOCUSING);
378bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.autoFocus((AutoFocusCallback) msg.obj);
379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
380bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
382cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CANCEL_AUTO_FOCUS: {
383bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.cancelAutoFocus();
384cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
385bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
386bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
387bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
388cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: {
389bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setAutoFocusMoveCallback(mCamera, msg.obj);
390bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
391bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
392bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
393cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_DISPLAY_ORIENTATION: {
394bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setDisplayOrientation(msg.arg1);
395bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
396bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
397bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
398cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ZOOM_CHANGE_LISTENER: {
399bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setZoomChangeListener((OnZoomChangeListener) msg.obj);
400bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
401bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
402bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
403cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_FACE_DETECTION_LISTENER: {
404bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setFaceDetectionListener((FaceDetectionListener) msg.obj);
405bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
406bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
407bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
408cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_FACE_DETECTION: {
409bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        startFaceDetection();
410bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
411bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
412bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
413cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_FACE_DETECTION: {
414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        stopFaceDetection();
415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
416bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
418cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ERROR_CALLBACK: {
419bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setErrorCallback((ErrorCallback) msg.obj);
420bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
421bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
422bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
423cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PARAMETERS: {
424bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParametersIsDirty = true;
425bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParamsToSet.unflatten((String) msg.obj);
426bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setParameters(mParamsToSet);
427bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
428bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
429bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
430cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.GET_PARAMETERS: {
431bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mParametersIsDirty) {
432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParameters = mCamera.getParameters();
433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParametersIsDirty = false;
434bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
435bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
436bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
438cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK: {
439bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallback((PreviewCallback) msg.obj);
440bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
441bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
442bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
443cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ENABLE_SHUTTER_SOUND: {
444bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        enableShutterSound((msg.arg1 == 1) ? true : false);
445bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
446bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
447bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
448cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.REFRESH_PARAMETERS: {
449bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParametersIsDirty = true;
450bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
451bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
452bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
453cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CAPTURE_PHOTO: {
454cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_CAPTURING);
455bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        capture((CaptureCallbacks) msg.obj);
456bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
457bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
459bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    default: {
460bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
461bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
462bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
463bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (final RuntimeException e) {
464cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                if (msg.what != CameraActions.RELEASE && mCamera != null) {
465bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
466bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.release();
467cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_UNOPENED);
468bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } catch (Exception ex) {
469bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.e(TAG, "Fail to release the camera.");
470bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
471bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCamera = null;
472bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                } else {
473bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (mCamera == null) {
474cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        if (msg.what == CameraActions.OPEN_CAMERA) {
475b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                            final int cameraId = msg.arg1;
476bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (msg.obj != null) {
477b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(
478b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                        msg.arg1, generateHistoryString(cameraId));
479bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
480bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
481bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null.");
482bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
483bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        return;
484bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
485bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
486bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                synchronized (mCameraExceptionCallback) {
487bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraExceptionCallbackHandler.post(new Runnable() {
488bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
489bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
490bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                mCameraExceptionCallback.onCameraException(e);
491bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
492bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        });
493bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
494bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
495bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
496bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
497bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
498bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
49960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    public void openCamera(final Handler handler, final int cameraId,
50060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                           final CameraOpenCallback callback) {
501bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.runJob(new Runnable() {
502bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
503bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void run() {
504cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                mCameraHandler.obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0,
505bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
506bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
507bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        });
508bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
509bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
51060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
51160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    public void closeCamera(CameraProxy camera, boolean synced) {
51260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        if (synced) {
51360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
51460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
51560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            mDispatchThread.runJobSync(new Runnable() {
51660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                @Override
51760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                public void run() {
518cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.RELEASE).sendToTarget();
51960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
52060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                }
52160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera release");
52260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        } else {
52360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            mDispatchThread.runJob(new Runnable() {
52460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                @Override
52560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                public void run() {
52660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.removeCallbacksAndMessages(null);
527cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.RELEASE).sendToTarget();
52860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                }
52960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            });
53060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        }
53160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    }
53260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
533bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
534bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A class which implements {@link CameraManager.CameraProxy} and
535bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera handler thread.
536bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
537bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
538bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final int mCameraId;
539bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /* TODO: remove this Camera instance. */
540bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Camera mCamera;
541c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private final AndroidCameraCapabilities mCapabilities;
542bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
543c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private AndroidCameraProxyImpl(int cameraId, Camera camera,
544c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                AndroidCameraCapabilities capabilities) {
545bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
546bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraId = cameraId;
547c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            mCapabilities = capabilities;
548bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
549bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
550bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
551bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public android.hardware.Camera getCamera() {
552bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCamera;
553bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
554bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
555bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
556bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public int getCameraId() {
557bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCameraId;
558bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
559bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
560bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
561c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        public CameraCapabilities getCapabilities() {
562c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            return new AndroidCameraCapabilities(mCapabilities);
563c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        }
564c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong
565c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        @Override
566bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void reconnect(final Handler handler, final CameraOpenCallback cb) {
567bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
568bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
569bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
570cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.RECONNECT, mCameraId, 0,
571bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget();
572bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
573bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
574bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
575bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
576bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void unlock() {
578bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
580bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
581bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
582cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.UNLOCK);
583bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
584bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
585bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera unlock");
586bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
587bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
588bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
589bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void lock() {
590bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
591bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
592bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
593cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.LOCK);
594bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
595bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
596bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
597bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
598bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
599bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewTexture(final SurfaceTexture surfaceTexture) {
600bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
601bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
602bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
603cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
604cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
605bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
606bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
607bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
608bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
609bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
610bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
611bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) {
612bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
613bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
614bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
615bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
616cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
617cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
618bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
619bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
620bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
621bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "set preview texture");
622bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
623bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
624bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
625bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDisplay(final SurfaceHolder surfaceHolder) {
626bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
627bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
628bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
629cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
630cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder)
631bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
632bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
633bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
634bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
635bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
636bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
637bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startPreview() {
638bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
639bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
640bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
641cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
642cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.START_PREVIEW_ASYNC, null).sendToTarget();
643bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
644bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
645bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
646bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
647bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
648bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startPreviewWithCallback(final Handler handler,
649bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraStartPreviewCallback cb) {
650bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
651bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
652bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
653cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.START_PREVIEW_ASYNC,
654bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        CameraStartPreviewCallbackForward.getNewInstance(handler, cb)).sendToTarget();
655bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
656bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
657bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
658bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
659bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
660bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void stopPreview() {
661bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
662bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
663bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
664bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
665cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.STOP_PREVIEW);
666bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
667bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
668bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "stop preview");
669bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
670bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
671bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
672bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallback(
673bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
674bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
675bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
676bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
677cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK,
678cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            PreviewCallbackForward.getNewInstance(
679cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
680bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
681bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
682bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
683bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
684bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
685bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setOneShotPreviewCallback(final Handler handler,
686bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPreviewDataCallback cb) {
687bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
688bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
689bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
690cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK,
691bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
692bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
693bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
694bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
695bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
696bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
697bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
698bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
699bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallbackWithBuffer(
700bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
701bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
702bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
703bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
704cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER,
705bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
706bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
707bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
708bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
709bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
710bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
711bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
712bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
713bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void addCallbackBuffer(final byte[] callbackBuffer) {
714bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
715bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
716bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
717cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.ADD_CALLBACK_BUFFER, callbackBuffer)
718bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
719bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
720bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
721bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
722bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
723bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
724bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void autoFocus(final Handler handler, final CameraAFCallback cb) {
725bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final AutoFocusCallback afCallback = new AutoFocusCallback() {
726bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
727bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onAutoFocus(final boolean b, Camera camera) {
728cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    if (mCameraState.getState() != CameraStateHolder.CAMERA_FOCUSING) {
729bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.w(TAG, "onAutoFocus callback returning when not focusing");
730bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
731cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
732bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
733bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
734bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
735bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
736bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cb.onAutoFocus(b, AndroidCameraProxyImpl.this);
737bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
738bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
739bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
740bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
741bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
742bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
743bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
744cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraState.waitForStates(CameraStateHolder.CAMERA_IDLE);
745cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, afCallback)
746cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
747bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
748bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
749bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
750bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
751bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
752bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void cancelAutoFocus() {
753bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
754bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
755bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
756cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.removeMessages(CameraActions.AUTO_FOCUS);
757cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.CANCEL_AUTO_FOCUS);
758bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
759bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
760bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
761bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
762bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
763bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
764bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setAutoFocusMoveCallback(
765bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraAFMoveCallback cb) {
766bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
767bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
768bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
769cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK,
770cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            AFMoveCallbackForward.getNewInstance(
771cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
772bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
773bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
774bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
775bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
776bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
777bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
778bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void takePicture(
779bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraShutterCallback shutter,
780bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback raw, final CameraPictureCallback post,
781bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback jpeg) {
782bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final PictureCallback jpegCallback = new PictureCallback() {
783bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
784bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onPictureTaken(final byte[] data, Camera camera) {
785cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    if (mCameraState.getState() != CameraStateHolder.CAMERA_CAPTURING) {
78660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        Log.w(TAG, "picture callback returning when not capturing");
787bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
788cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
789bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
790bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
791bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
792bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
793bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpeg.onPictureTaken(data, AndroidCameraProxyImpl.this);
794bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
795bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
796bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
797bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
798bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
799bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
800bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
801bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
802cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraState.waitForStates(
803cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            CameraStateHolder.CAMERA_IDLE | CameraStateHolder.CAMERA_UNLOCKED);
804bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.requestTakePicture(ShutterCallbackForward
805bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .getNewInstance(handler, AndroidCameraProxyImpl.this, shutter),
806bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
807bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, raw),
808bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
809bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, post),
810bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpegCallback);
811bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
812bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
813bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
814bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
815bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
816bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setDisplayOrientation(final int degrees) {
817bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
818bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
819bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
820cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_DISPLAY_ORIENTATION, degrees, 0)
821bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
822bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
823bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
824bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
825bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
826bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
827bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setZoomChangeListener(final OnZoomChangeListener listener) {
828bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
829bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
830bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
831cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ZOOM_CHANGE_LISTENER, listener)
832cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
833bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
834bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
835bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
836bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
837bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
838bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setFaceDetectionCallback(final Handler handler,
839bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraFaceDetectionCallback cb) {
840bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
841bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
842bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
843cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_FACE_DETECTION_LISTENER,
844bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            FaceDetectionCallbackForward
845bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
846bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
847bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
848bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
849bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
850bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
851bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
852bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startFaceDetection() {
853bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
854bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
855bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
856cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.START_FACE_DETECTION);
857bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
858bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
859bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
860bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
861bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
862bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void stopFaceDetection() {
863bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
864bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
865bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
866cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.STOP_FACE_DETECTION);
867bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
868bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
869bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
870bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
871bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
872bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setErrorCallback(final Handler handler, final CameraErrorCallback cb) {
873bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
874bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
875bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
876cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ERROR_CALLBACK,
877cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            ErrorCallbackForward.getNewInstance(
878cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
879cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
880bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
881bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
882bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
883bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
884bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
885bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setParameters(final Parameters params) {
886bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (params == null) {
887bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.v(TAG, "null parameters in setParameters()");
888bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return;
889bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
890bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final String flattenedParameters = params.flatten();
891bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
892bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
893bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
894cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraState.waitForStates(
895cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            CameraStateHolder.CAMERA_IDLE | CameraStateHolder.CAMERA_UNLOCKED);
896cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PARAMETERS, flattenedParameters)
897cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
898bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
899bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
900bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
901bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
902bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
903bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Parameters getParameters() {
904bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
905bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
906bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
907bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
908cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.GET_PARAMETERS);
909bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
910bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
911bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "get parameters");
912bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mParameters;
913bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
914bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
915bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
916bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void refreshParameters() {
917bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
918bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
919bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
920cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.REFRESH_PARAMETERS);
921bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
922bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
923bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
924bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
925bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
926bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void enableShutterSound(final boolean enable) {
927bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
928bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
929bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
930cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
931cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0)
932bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
933bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
934bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
935bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
936bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
937bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
938bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class WaitDoneBundle {
939bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Runnable mUnlockRunnable;
940bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Object mWaitLock;
941bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
942bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        WaitDoneBundle() {
943bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mWaitLock = new Object();
944bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mUnlockRunnable = new Runnable() {
945bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
946bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
947bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    synchronized (mWaitLock) {
948bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mWaitLock.notifyAll();
949bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
950bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
951bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
952bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
953bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
954bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
955bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
956bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward AutoFocusCallback to another thread.
957bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
958bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFCallbackForward implements AutoFocusCallback {
959bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
960bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
961bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFCallback mCallback;
962bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
963bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
964bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
965bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
966bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
967bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
968bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
969bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
970bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
971bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
972bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFCallbackForward getNewInstance(
973bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFCallback cb) {
974bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
975bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
976bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
977bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFCallbackForward(handler, camera, cb);
978bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
979bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
980bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFCallbackForward(
981bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFCallback cb) {
982bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
983bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
984bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
985bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
986bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
987bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
988bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocus(final boolean b, Camera camera) {
989bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
990bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
991bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
992bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocus(b, mCamera);
993bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
994bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
995bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
996bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
997bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
998bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
999bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ErrorCallback to another thread.
1000bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1001bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ErrorCallbackForward implements Camera.ErrorCallback {
1002bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1003bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1004bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraErrorCallback mCallback;
1005bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1006bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1007bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1008bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1009bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1010bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1011bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1012bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1013bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1014bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1015bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ErrorCallbackForward getNewInstance(
1016bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraErrorCallback cb) {
1017bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1018bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1019bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1020bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ErrorCallbackForward(handler, camera, cb);
1021bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1022bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1023bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ErrorCallbackForward(
1024bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraErrorCallback cb) {
1025bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1026bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1027bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1028bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1029bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1030bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1031bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onError(final int error, Camera camera) {
1032bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1033bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1034bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1035bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onError(error, mCamera);
1036bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1037bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1038bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1039bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1040bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1041bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /** A helper class to forward AutoFocusMoveCallback to another thread. */
1042bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1043bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
1044bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1045bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFMoveCallback mCallback;
1046bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1047bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1048bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1049bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFMoveCallbackForward}.
1050bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1051bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1052bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1053bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1054bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFMoveCallbackForward},
1055bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1056bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1057bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFMoveCallbackForward getNewInstance(
1058bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
1059bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1060bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1061bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1062bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFMoveCallbackForward(handler, camera, cb);
1063bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1064bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1065bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFMoveCallbackForward(
1066bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
1067bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1068bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1069bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1070bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1071bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1072bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1073bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocusMoving(
1074bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final boolean moving, android.hardware.Camera camera) {
1075bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1076bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1077bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1078bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocusMoving(moving, mCamera);
1079bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1080bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1081bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1082bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1083bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1084bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1085bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ShutterCallback to to another thread.
1086bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1087bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ShutterCallbackForward implements ShutterCallback {
1088bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1089bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraShutterCallback mCallback;
1090bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1091bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1092bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1093bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link ShutterCallbackForward}.
1094bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1095bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1096bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1097bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1098bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link ShutterCallbackForward},
1099bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1100bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1101bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ShutterCallbackForward getNewInstance(
1102bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraShutterCallback cb) {
1103bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1104bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1105bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1106bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ShutterCallbackForward(handler, camera, cb);
1107bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1108bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1109bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ShutterCallbackForward(
1110bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraShutterCallback cb) {
1111bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1112bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1113bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1114bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1115bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1116bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1117bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onShutter() {
1118bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1119bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1120bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1121bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onShutter(mCamera);
1122bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1123bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1124bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1125bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1126bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1127bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1128bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PictureCallback to another thread.
1129bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1130bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PictureCallbackForward implements PictureCallback {
1131bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1132bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPictureCallback mCallback;
1133bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1134bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1135bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1136bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PictureCallbackForward}.
1137bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1138bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1139bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1140bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1141bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PictureCallbackForward},
1142bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1143bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1144bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PictureCallbackForward getNewInstance(
1145bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPictureCallback cb) {
1146bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1147bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1148bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1149bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PictureCallbackForward(handler, camera, cb);
1150bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1151bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1152bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PictureCallbackForward(
1153bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPictureCallback cb) {
1154bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1155bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1156bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1157bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1158bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1159bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1160bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPictureTaken(
1161bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1164bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1165bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPictureTaken(data, mCamera);
1166bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1167bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1168bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1169bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1170bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PreviewCallback to another thread.
1173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PreviewCallbackForward implements PreviewCallback {
1175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPreviewDataCallback mCallback;
1177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PreviewCallbackForward}.
1181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PreviewCallbackForward},
1186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PreviewCallbackForward getNewInstance(
1189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
1190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PreviewCallbackForward(handler, camera, cb);
1194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PreviewCallbackForward(
1197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
1198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewFrame(
1205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1209bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPreviewFrame(data, mCamera);
1210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class FaceDetectionCallbackForward implements FaceDetectionListener {
1216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraFaceDetectionCallback mCallback;
1218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
1222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link FaceDetectionCallbackForward},
1227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static FaceDetectionCallbackForward getNewInstance(
1230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
1231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new FaceDetectionCallbackForward(handler, camera, cb);
1235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private FaceDetectionCallbackForward(
1238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
1239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onFaceDetection(
1246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Camera.Face[] faces, Camera camera) {
1247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onFaceDetection(faces, mCamera);
1251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong}
1256