AndroidCameraAgentImpl.java revision f07afbbde040b9578bc7f188016c3960e8616ab0
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.view.SurfaceHolder;
37bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
38bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport com.android.ex.camera2.portability.debug.Log;
39bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
40bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongimport java.io.IOException;
41bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
42bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/**
43bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong * A class to implement {@link CameraManager} of the Android camera framework.
44bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong */
45bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kongclass AndroidCameraManagerImpl implements CameraManager {
46bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static final Log.Tag TAG = new Log.Tag("AndroidCamMgrImpl");
47bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
48bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Parameters mParameters;
49bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private boolean mParametersIsDirty;
508097973089420749dcd1ab4974a629c2466b31ccAngus Kong    private AndroidCameraCapabilities mCapabilities;
51bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
52bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraHandler mCameraHandler;
53bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final HandlerThread mCameraHandlerThread;
54bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraStateHolder mCameraState;
55bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final DispatchThread mDispatchThread;
56bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
57bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Handler mCameraExceptionCallbackHandler;
58bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private CameraExceptionCallback mCameraExceptionCallback =
59bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        new CameraExceptionCallback() {
60bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
61bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void onCameraException(RuntimeException e) {
62bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
63bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
64bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        };
65bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
66bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    AndroidCameraManagerImpl() {
67bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread = new HandlerThread("Camera Handler Thread");
68bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread.start();
69bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandler = new CameraHandler(mCameraHandlerThread.getLooper());
70bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraExceptionCallbackHandler = mCameraHandler;
71bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraState = new CameraStateHolder();
72cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread);
73bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.start();
74bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
75bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
76bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
77bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback,
78bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            Handler handler) {
79bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        synchronized (mCameraExceptionCallback) {
80bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallback = callback;
81bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallbackHandler = handler;
82bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
83bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
84bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
8560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
86bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void recycle() {
8760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        closeCamera(null, true);
88bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.end();
89bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
907e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
917e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    @Override
927e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    public CameraDeviceInfo getCameraDeviceInfo() {
937e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        return AndroidCameraDeviceInfo.create();
947e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
957e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
967e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    private static class AndroidCameraDeviceInfo implements CameraDeviceInfo {
977e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final Camera.CameraInfo[] mCameraInfos;
987e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mNumberOfCameras;
997e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstBackCameraId;
1007e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstFrontCameraId;
1017e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1027e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private AndroidCameraDeviceInfo(Camera.CameraInfo[] info, int numberOfCameras,
1037e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                int firstBackCameraId, int firstFrontCameraId) {
1047e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1057e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mCameraInfos = info;
1067e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mNumberOfCameras = numberOfCameras;
1077e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstBackCameraId = firstBackCameraId;
1087e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstFrontCameraId = firstFrontCameraId;
1097e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1107e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1117e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public static AndroidCameraDeviceInfo create() {
1127e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int numberOfCameras;
1137e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            Camera.CameraInfo[] cameraInfos;
1147e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            try {
1157e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                numberOfCameras = Camera.getNumberOfCameras();
1167e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                cameraInfos = new Camera.CameraInfo[numberOfCameras];
1177e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                for (int i = 0; i < numberOfCameras; i++) {
1187e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    cameraInfos[i] = new Camera.CameraInfo();
1197e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    Camera.getCameraInfo(i, cameraInfos[i]);
1207e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1217e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            } catch (RuntimeException ex) {
1227e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                return null;
1237e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1247e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1257e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstFront = NO_DEVICE;
1267e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstBack = NO_DEVICE;
1277e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            // Get the first (smallest) back and first front camera id.
1287e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            for (int i = numberOfCameras - 1; i >= 0; i--) {
1297e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
1307e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    firstBack = i;
1317e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                } else {
1327e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
1337e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                        firstFront = i;
1347e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    }
1357e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1367e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1377e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1387e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return new AndroidCameraDeviceInfo(cameraInfos, numberOfCameras, firstBack, firstFront);
1397e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1407e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1417e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1427e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public Camera.CameraInfo[] getCameraInfos() {
1437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mCameraInfos;
1447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1457e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getNumberOfCameras() {
1487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mNumberOfCameras;
1497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1507e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1517e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1527e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstBackCameraId() {
1537e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstBackCameraId;
1547e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1557e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1567e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1577e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstFrontCameraId() {
1587e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstFrontCameraId;
1597e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1607e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
161bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * The handler on which the actual camera operations happen.
164bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
165cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    private class CameraHandler extends HistoryHandler {
166b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong
1678097973089420749dcd1ab4974a629c2466b31ccAngus Kong        // Used to retain a copy of Parameters for setting parameters.
1688097973089420749dcd1ab4974a629c2466b31ccAngus Kong        private Parameters mParamsToSet;
169bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private Camera mCamera;
17060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        private int mCameraId;
171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private class CaptureCallbacks {
173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final ShutterCallback mShutter;
174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mRaw;
175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mPostView;
176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mJpeg;
177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            CaptureCallbacks(ShutterCallback shutter, PictureCallback raw, PictureCallback postView,
179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    PictureCallback jpeg) {
180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mShutter = shutter;
181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mRaw = raw;
182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mPostView = postView;
183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJpeg = jpeg;
184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        CameraHandler(Looper looper) {
188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            super(looper);
189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void startFaceDetection() {
192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.startFaceDetection();
193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void stopFaceDetection() {
196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.stopFaceDetection();
197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setFaceDetectionListener(FaceDetectionListener listener) {
200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.setFaceDetectionListener(listener);
201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setPreviewTexture(Object surfaceTexture) {
204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (IOException e) {
207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "Could not set preview texture", e);
208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
209bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void enableShutterSound(boolean enable) {
213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.enableShutterSound(enable);
214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setAutoFocusMoveCallback(
218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                android.hardware.Camera camera, Object cb) {
219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException ex) {
222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.w(TAG, ex.getMessage());
223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void capture(final CaptureCallbacks cb) {
227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.takePicture(cb.mShutter, cb.mRaw, cb.mPostView, cb.mJpeg);
229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException e) {
230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                // TODO: output camera state and focus state for debugging.
231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "take picture failed.");
232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void requestTakePicture(
237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final ShutterCallback shutter,
238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback raw,
239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback postView,
240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback jpeg) {
241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final CaptureCallbacks callbacks = new CaptureCallbacks(shutter, raw, postView, jpeg);
242cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            obtainMessage(CameraActions.CAPTURE_PHOTO, callbacks).sendToTarget();
243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * This method does not deal with the API level check.  Everyone should
247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * check first for supported operations before sending message to this handler.
248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void handleMessage(final Message msg) {
251cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            super.handleMessage(msg);
252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                switch (msg.what) {
254cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.OPEN_CAMERA: {
255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
257cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        if (mCameraState.getState() != CameraStateHolder.CAMERA_UNOPENED) {
25860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera = android.hardware.Camera.open(cameraId);
263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mCamera != null) {
26460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCameraId = cameraId;
265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParametersIsDirty = true;
266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            // Get a instance of Camera.Parameters for later use.
268742beb4e81cfcdfa9d4f7d3252be7be797a1e462Sascha Haeberling                            mParamsToSet = mCamera.getParameters();
2698097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            mCapabilities = new AndroidCameraCapabilities(mParamsToSet);
270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
271cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                openCallback.onCameraOpened(
274c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                        new AndroidCameraProxyImpl(cameraId, mCamera,
2758097973089420749dcd1ab4974a629c2466b31ccAngus Kong                                                mCapabilities));
276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
279b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
285cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RELEASE: {
28660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        if (mCamera != null) {
28760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera.release();
288cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            mCameraState.setState(CameraStateHolder.CAMERA_UNOPENED);
28960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera = null;
29060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        } else {
29160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            Log.w(TAG, "Releasing camera without any camera opened.");
29260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        }
293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
296cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RECONNECT: {
297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallbackForward cbForward =
298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                (CameraOpenCallbackForward) msg.obj;
299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.reconnect();
302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException ex) {
303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (cbForward != null) {
30460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                cbForward.onReconnectionFailure(AndroidCameraManagerImpl.this,
30560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                        generateHistoryString(mCameraId));
306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
307bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
310cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
3128097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            cbForward.onCameraOpened(
3138097973089420749dcd1ab4974a629c2466b31ccAngus Kong                                    new AndroidCameraProxyImpl(cameraId, mCamera, mCapabilities));
314bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
315bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
318cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.UNLOCK: {
319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.unlock();
320cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_UNLOCKED);
321bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
322bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
324cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.LOCK: {
325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.lock();
326cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
328bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
330cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: {
331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setPreviewTexture(msg.obj);
332bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
335cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: {
336bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
337bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
338bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException e) {
339bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            throw new RuntimeException(e);
340bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
341bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
342bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
343bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
344cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_PREVIEW_ASYNC: {
345bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraStartPreviewCallbackForward cbForward =
346bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            (CameraStartPreviewCallbackForward) msg.obj;
347bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.startPreview();
348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cbForward.onPreviewStarted();
350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
354cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_PREVIEW: {
355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.stopPreview();
356bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
357bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
358bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
359cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: {
360bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallbackWithBuffer((PreviewCallback) msg.obj);
361bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
362bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
363bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
364cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: {
365bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setOneShotPreviewCallback((PreviewCallback) msg.obj);
366bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
368bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
369cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ADD_CALLBACK_BUFFER: {
370bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.addCallbackBuffer((byte[]) msg.obj);
371bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
372bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
374cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.AUTO_FOCUS: {
375cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_FOCUSING);
376bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.autoFocus((AutoFocusCallback) msg.obj);
377bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
378bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
380cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CANCEL_AUTO_FOCUS: {
381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.cancelAutoFocus();
382cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
383bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
384bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
385bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
386cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: {
387bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setAutoFocusMoveCallback(mCamera, msg.obj);
388bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
389bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
390bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
391cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_DISPLAY_ORIENTATION: {
392bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setDisplayOrientation(msg.arg1);
393bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
394bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
395bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
396cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ZOOM_CHANGE_LISTENER: {
397bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setZoomChangeListener((OnZoomChangeListener) msg.obj);
398bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
399bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
400bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
401cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_FACE_DETECTION_LISTENER: {
402bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setFaceDetectionListener((FaceDetectionListener) msg.obj);
403bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
404bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
405bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
406cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_FACE_DETECTION: {
407bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        startFaceDetection();
408bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
409bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
410bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
411cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_FACE_DETECTION: {
412bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        stopFaceDetection();
413bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
416cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ERROR_CALLBACK: {
417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setErrorCallback((ErrorCallback) msg.obj);
418bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
419bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
420bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
4218097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    case CameraActions.APPLY_SETTINGS: {
4228097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        mParametersIsDirty = true;
4238097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        CameraSettings settings = (CameraSettings) msg.obj;
4248097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        applyToParameters(settings);
4258097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        mCamera.setParameters(mParamsToSet);
4268097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        break;
4278097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    }
4288097973089420749dcd1ab4974a629c2466b31ccAngus Kong
429cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PARAMETERS: {
430bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParametersIsDirty = true;
431bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParamsToSet.unflatten((String) msg.obj);
432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setParameters(mParamsToSet);
433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
434bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
435bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
436cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.GET_PARAMETERS: {
437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mParametersIsDirty) {
438bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParameters = mCamera.getParameters();
439bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mParametersIsDirty = false;
440bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
441bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
442bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
443bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
444cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK: {
445bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallback((PreviewCallback) msg.obj);
446bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
447bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
448bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
449cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ENABLE_SHUTTER_SOUND: {
450bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        enableShutterSound((msg.arg1 == 1) ? true : false);
451bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
452bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
453bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
454cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.REFRESH_PARAMETERS: {
455bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mParametersIsDirty = true;
456bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
457bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
459cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CAPTURE_PHOTO: {
460cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_CAPTURING);
461bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        capture((CaptureCallbacks) msg.obj);
462bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
463bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
464bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
465bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    default: {
466bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
467bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
468bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
469bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (final RuntimeException e) {
470cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                if (msg.what != CameraActions.RELEASE && mCamera != null) {
471bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
472bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.release();
473cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_UNOPENED);
474bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } catch (Exception ex) {
475bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.e(TAG, "Fail to release the camera.");
476bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
477bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCamera = null;
478bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                } else {
479bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (mCamera == null) {
480cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        if (msg.what == CameraActions.OPEN_CAMERA) {
481b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                            final int cameraId = msg.arg1;
482bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (msg.obj != null) {
483b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(
484b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                        msg.arg1, generateHistoryString(cameraId));
485bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
486bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
487bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null.");
488bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
489bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        return;
490bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
491bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
492bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                synchronized (mCameraExceptionCallback) {
493bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraExceptionCallbackHandler.post(new Runnable() {
494bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
495bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
496bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                mCameraExceptionCallback.onCameraException(e);
497bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
498bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        });
499bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
500bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
501bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
5028097973089420749dcd1ab4974a629c2466b31ccAngus Kong
5038097973089420749dcd1ab4974a629c2466b31ccAngus Kong        private void applyToParameters(final CameraSettings settings) {
5048097973089420749dcd1ab4974a629c2466b31ccAngus Kong            final CameraCapabilities.Stringifier stringifier = mCapabilities.getStringifier();
5058097973089420749dcd1ab4974a629c2466b31ccAngus Kong            Size photoSize = settings.getCurrentPhotoSize();
5068097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mParamsToSet.setPictureSize(photoSize.width(), photoSize.height());
5078097973089420749dcd1ab4974a629c2466b31ccAngus Kong            Size previewSize = settings.getCurrentPreviewSize();
5088097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mParamsToSet.setPreviewSize(previewSize.width(), previewSize.height());
5098097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getPreviewFrameRate() == -1) {
5108097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setPreviewFpsRange(settings.getPreviewFpsRangeMin(),
5118097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        settings.getPreviewFpsRangeMax());
5128097973089420749dcd1ab4974a629c2466b31ccAngus Kong            } else {
5138097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setPreviewFrameRate(settings.getPreviewFrameRate());
5148097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5158097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mParamsToSet.setJpegQuality(settings.getPhotoJpegCompressionQuality());
5168097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.ZOOM)) {
5178097973089420749dcd1ab4974a629c2466b31ccAngus Kong                // Should use settings.getCurrentZoomRatio() instead here.
5188097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setZoom(settings.getCurrentZoomIndex());
5198097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5208097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mParamsToSet.setRotation((int) settings.getCurrentPhotoRotationDegrees());
5218097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mParamsToSet.setExposureCompensation(settings.getExposureCompensationIndex());
5228097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)) {
5238097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setAutoExposureLock(settings.isAutoExposureLocked());
5248097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5258097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mParamsToSet.setFocusMode(stringifier.stringify(settings.getCurrentFocusMode()));
5268097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK)) {
5278097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setAutoWhiteBalanceLock(settings.isAutoWhiteBalanceLocked());
5288097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5298097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA)) {
530f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getFocusAreas().size() != 0) {
531f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                    mParamsToSet.setFocusAreas(settings.getFocusAreas());
532f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
5338097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5348097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA)) {
535f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getMeteringAreas().size() != 0) {
536f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                    mParamsToSet.setMeteringAreas(settings.getMeteringAreas());
537f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
5388097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5398097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getCurrentFlashMode() != CameraCapabilities.FlashMode.NO_FLASH) {
5408097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setFlashMode(stringifier.stringify(settings.getCurrentFlashMode()));
5418097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5428097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getCurrentSceneMode() != CameraCapabilities.SceneMode.NO_SCENE_MODE) {
543f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getCurrentSceneMode() != null) {
544f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                    mParamsToSet
545f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                            .setSceneMode(stringifier.stringify(settings.getCurrentSceneMode()));
546f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
5478097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5488097973089420749dcd1ab4974a629c2466b31ccAngus Kong
5498097973089420749dcd1ab4974a629c2466b31ccAngus Kong            CameraSettings.GpsData gpsData = settings.getGpsData();
5508097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (gpsData == null) {
5518097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.removeGpsData();
5528097973089420749dcd1ab4974a629c2466b31ccAngus Kong            } else {
5538097973089420749dcd1ab4974a629c2466b31ccAngus Kong                mParamsToSet.setGpsTimestamp(gpsData.timeStamp);
5548097973089420749dcd1ab4974a629c2466b31ccAngus Kong                if (gpsData.processingMethod != null) {
5558097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // It's a hack since we always use GPS time stamp but does
5568097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // not use other fields sometimes. Setting processing
5578097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // method to null means the other fields should not be used.
5588097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    mParamsToSet.setGpsAltitude(gpsData.altitude);
5598097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    mParamsToSet.setGpsLatitude(gpsData.latitude);
5608097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    mParamsToSet.setGpsLongitude(gpsData.longitude);
5618097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    mParamsToSet.setGpsProcessingMethod(gpsData.processingMethod);
5628097973089420749dcd1ab4974a629c2466b31ccAngus Kong                }
5638097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
5648097973089420749dcd1ab4974a629c2466b31ccAngus Kong
5658097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
566bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
567bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
568bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
56960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    public void openCamera(final Handler handler, final int cameraId,
57060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                           final CameraOpenCallback callback) {
571bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.runJob(new Runnable() {
572bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
573bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void run() {
574cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                mCameraHandler.obtainMessage(CameraActions.OPEN_CAMERA, cameraId, 0,
575bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        CameraOpenCallbackForward.getNewInstance(handler, callback)).sendToTarget();
576bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        });
578bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
58060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
58160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    public void closeCamera(CameraProxy camera, boolean synced) {
58260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        if (synced) {
58360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
58460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
58560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            mDispatchThread.runJobSync(new Runnable() {
58660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                @Override
58760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                public void run() {
588cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.RELEASE).sendToTarget();
58960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
59060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                }
59160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera release");
59260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        } else {
59360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            mDispatchThread.runJob(new Runnable() {
59460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                @Override
59560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                public void run() {
59660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                    mCameraHandler.removeCallbacksAndMessages(null);
597cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.RELEASE).sendToTarget();
59860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                }
59960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong            });
60060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        }
60160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    }
60260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong
603bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
604bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A class which implements {@link CameraManager.CameraProxy} and
605bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera handler thread.
606bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
607bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private class AndroidCameraProxyImpl implements CameraManager.CameraProxy {
608bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final int mCameraId;
609bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /* TODO: remove this Camera instance. */
610bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Camera mCamera;
611c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private final AndroidCameraCapabilities mCapabilities;
612bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
613c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private AndroidCameraProxyImpl(int cameraId, Camera camera,
614c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                AndroidCameraCapabilities capabilities) {
615bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
616bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraId = cameraId;
617c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            mCapabilities = capabilities;
618bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
619bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
620bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
621bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public android.hardware.Camera getCamera() {
622bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCamera;
623bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
624bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
625bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
626bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public int getCameraId() {
627bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCameraId;
628bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
629bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
630bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
631c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        public CameraCapabilities getCapabilities() {
632c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            return new AndroidCameraCapabilities(mCapabilities);
633c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        }
634c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong
635c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        @Override
636bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void reconnect(final Handler handler, final CameraOpenCallback cb) {
637bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
638bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
639bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
640cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.RECONNECT, mCameraId, 0,
641bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            CameraOpenCallbackForward.getNewInstance(handler, cb)).sendToTarget();
642bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
643bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
644bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
645bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
646bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
647bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void unlock() {
648bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
649bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
650bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
651bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
652cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.UNLOCK);
653bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
654bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
655bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "camera unlock");
656bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
657bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
658bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
659bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void lock() {
660bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
661bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
662bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
663cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.LOCK);
664bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
665bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
666bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
667bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
668bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
669bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewTexture(final SurfaceTexture surfaceTexture) {
670bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
671bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
672bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
673cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
674cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
675bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
676bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
677bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
678bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
679bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
680bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
681bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewTextureSync(final SurfaceTexture surfaceTexture) {
682bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
683bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
684bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
685bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
686cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
687cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture)
688bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
689bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
690bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
691bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "set preview texture");
692bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
693bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
694bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
695bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDisplay(final SurfaceHolder surfaceHolder) {
696bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
697bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
698bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
699cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
700cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder)
701bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
702bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
703bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
704bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
705bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
706bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
707bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startPreview() {
708bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
709bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
710bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
711cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
712cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.START_PREVIEW_ASYNC, null).sendToTarget();
713bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
714bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
715bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
716bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
717bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
718bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startPreviewWithCallback(final Handler handler,
719bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraStartPreviewCallback cb) {
720bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
721bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
722bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
723cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.START_PREVIEW_ASYNC,
724bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        CameraStartPreviewCallbackForward.getNewInstance(handler, cb)).sendToTarget();
725bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
726bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
727bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
728bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
729bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
730bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void stopPreview() {
731bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
732bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
733bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
734bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
735cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.STOP_PREVIEW);
736bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
737bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
738bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "stop preview");
739bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
740bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
741bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
742bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallback(
743bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
744bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
745bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
746bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
747cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK,
748cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            PreviewCallbackForward.getNewInstance(
749cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
750bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
751bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
752bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
753bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
754bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
755bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setOneShotPreviewCallback(final Handler handler,
756bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPreviewDataCallback cb) {
757bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
758bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
759bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
760cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK,
761bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
762bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
763bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
764bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
765bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
766bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
767bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
768bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
769bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallbackWithBuffer(
770bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
771bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
772bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
773bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
774cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER,
775bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
776bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
777bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
778bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
779bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
780bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
781bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
782bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
783bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void addCallbackBuffer(final byte[] callbackBuffer) {
784bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
785bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
786bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
787cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.ADD_CALLBACK_BUFFER, callbackBuffer)
788bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
789bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
790bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
791bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
792bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
793bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
794bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void autoFocus(final Handler handler, final CameraAFCallback cb) {
795bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final AutoFocusCallback afCallback = new AutoFocusCallback() {
796bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
797bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onAutoFocus(final boolean b, Camera camera) {
798cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    if (mCameraState.getState() != CameraStateHolder.CAMERA_FOCUSING) {
799bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.w(TAG, "onAutoFocus callback returning when not focusing");
800bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
801cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
802bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
803bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
804bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
805bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
806bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cb.onAutoFocus(b, AndroidCameraProxyImpl.this);
807bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
808bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
809bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
810bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
811bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
812bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
813bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
814cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraState.waitForStates(CameraStateHolder.CAMERA_IDLE);
815cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, afCallback)
816cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
817bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
818bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
819bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
820bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
821bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
822bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void cancelAutoFocus() {
823bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
824bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
825bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
826cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.removeMessages(CameraActions.AUTO_FOCUS);
827cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.CANCEL_AUTO_FOCUS);
828bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
829bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
830bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
831bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
832bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
833bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
834bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setAutoFocusMoveCallback(
835bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraAFMoveCallback cb) {
836bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
837bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
838bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
839cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK,
840cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            AFMoveCallbackForward.getNewInstance(
841cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
842bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
843bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
844bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
845bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
846bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
847bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
848bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void takePicture(
849bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraShutterCallback shutter,
850bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback raw, final CameraPictureCallback post,
851bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback jpeg) {
852bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final PictureCallback jpegCallback = new PictureCallback() {
853bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
854bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onPictureTaken(final byte[] data, Camera camera) {
855cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    if (mCameraState.getState() != CameraStateHolder.CAMERA_CAPTURING) {
85660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        Log.w(TAG, "picture callback returning when not capturing");
857bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
858cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        mCameraState.setState(CameraStateHolder.CAMERA_IDLE);
859bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
860bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
861bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
862bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
863bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpeg.onPictureTaken(data, AndroidCameraProxyImpl.this);
864bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
865bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
866bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
867bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
868bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
869bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
870bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
871bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
872cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraState.waitForStates(
873cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            CameraStateHolder.CAMERA_IDLE | CameraStateHolder.CAMERA_UNLOCKED);
874bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.requestTakePicture(ShutterCallbackForward
8758097973089420749dcd1ab4974a629c2466b31ccAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, shutter),
876bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
877bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, raw),
878bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
879bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, post),
8808097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            jpegCallback
8818097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    );
882bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
883bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
884bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
885bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
886bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
887bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setDisplayOrientation(final int degrees) {
888bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
889bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
890bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
891cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_DISPLAY_ORIENTATION, degrees, 0)
892bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
893bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
894bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
895bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
896bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
897bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
898bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setZoomChangeListener(final OnZoomChangeListener listener) {
899bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
900bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
901bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
902cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ZOOM_CHANGE_LISTENER, listener)
903cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
904bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
905bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
906bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
907bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
908bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
909bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setFaceDetectionCallback(final Handler handler,
910bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraFaceDetectionCallback cb) {
911bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
912bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
913bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
914cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_FACE_DETECTION_LISTENER,
915bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            FaceDetectionCallbackForward
916bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
917bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
918bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
919bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
920bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
921bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
922bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
923bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void startFaceDetection() {
924bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
925bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
926bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
927cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.START_FACE_DETECTION);
928bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
929bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
930bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
931bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
932bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
933bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void stopFaceDetection() {
934bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
935bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
936bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
937cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.STOP_FACE_DETECTION);
938bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
939bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
940bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
941bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
942bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
943bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setErrorCallback(final Handler handler, final CameraErrorCallback cb) {
944bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
945bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
946bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
947cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ERROR_CALLBACK,
948cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            ErrorCallbackForward.getNewInstance(
949cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
950cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
951bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
952bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
953bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
954bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
955bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
956bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setParameters(final Parameters params) {
957bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (params == null) {
958bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.v(TAG, "null parameters in setParameters()");
959bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return;
960bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
961bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final String flattenedParameters = params.flatten();
962bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
963bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
964bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
965cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraState.waitForStates(
966cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            CameraStateHolder.CAMERA_IDLE | CameraStateHolder.CAMERA_UNLOCKED);
967cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PARAMETERS, flattenedParameters)
968cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
969bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
970bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
971bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
972bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
973bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
974bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Parameters getParameters() {
975bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
976bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
977bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
978bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
979cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.GET_PARAMETERS);
980bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
981bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
982bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "get parameters");
983bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mParameters;
984bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
985bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
986bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
9878097973089420749dcd1ab4974a629c2466b31ccAngus Kong        public CameraSettings getSettings() {
9888097973089420749dcd1ab4974a629c2466b31ccAngus Kong            return new AndroidCameraSettings(mCapabilities, getParameters());
9898097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
9908097973089420749dcd1ab4974a629c2466b31ccAngus Kong
9918097973089420749dcd1ab4974a629c2466b31ccAngus Kong        @Override
9928097973089420749dcd1ab4974a629c2466b31ccAngus Kong        public boolean applySettings(final CameraSettings settings) {
9938097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings == null) {
9948097973089420749dcd1ab4974a629c2466b31ccAngus Kong                Log.v(TAG, "null parameters in applySettings()");
9958097973089420749dcd1ab4974a629c2466b31ccAngus Kong                return false;
9968097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
9978097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (!mCapabilities.supports(settings)) {
9988097973089420749dcd1ab4974a629c2466b31ccAngus Kong                return false;
9998097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
10008097973089420749dcd1ab4974a629c2466b31ccAngus Kong
10018097973089420749dcd1ab4974a629c2466b31ccAngus Kong            final CameraSettings copyOfSettings = new CameraSettings(settings);
10028097973089420749dcd1ab4974a629c2466b31ccAngus Kong            mDispatchThread.runJob(new Runnable() {
10038097973089420749dcd1ab4974a629c2466b31ccAngus Kong                @Override
10048097973089420749dcd1ab4974a629c2466b31ccAngus Kong                public void run() {
10058097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    mCameraState.waitForStates(
10068097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            CameraStateHolder.CAMERA_IDLE | CameraStateHolder.CAMERA_UNLOCKED);
10078097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    mCameraHandler.obtainMessage(CameraActions.APPLY_SETTINGS, copyOfSettings)
10088097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            .sendToTarget();
10098097973089420749dcd1ab4974a629c2466b31ccAngus Kong                }
10108097973089420749dcd1ab4974a629c2466b31ccAngus Kong            });
10118097973089420749dcd1ab4974a629c2466b31ccAngus Kong            return true;
10128097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
10138097973089420749dcd1ab4974a629c2466b31ccAngus Kong
10148097973089420749dcd1ab4974a629c2466b31ccAngus Kong        @Override
10158097973089420749dcd1ab4974a629c2466b31ccAngus Kong        public void refreshSettings() {
1016bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1017bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1018bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1019cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.sendEmptyMessage(CameraActions.REFRESH_PARAMETERS);
1020bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1021bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1022bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1023bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1024bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1025bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void enableShutterSound(final boolean enable) {
1026bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
1027bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1028bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1029cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler
1030cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .obtainMessage(CameraActions.ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0)
1031bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
1032bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1033bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1034bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1035bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1036bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1037bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class WaitDoneBundle {
1038bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Runnable mUnlockRunnable;
1039bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Object mWaitLock;
1040bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1041bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        WaitDoneBundle() {
1042bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mWaitLock = new Object();
1043bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mUnlockRunnable = new Runnable() {
1044bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1045bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1046bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    synchronized (mWaitLock) {
1047bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mWaitLock.notifyAll();
1048bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
1049bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1050bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
1051bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1052bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1053bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1054bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1055bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward AutoFocusCallback to another thread.
1056bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1057bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFCallbackForward implements AutoFocusCallback {
1058bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1059bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1060bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFCallback mCallback;
1061bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1062bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1063bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1064bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1065bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1066bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1067bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1068bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1069bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1070bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1071bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFCallbackForward getNewInstance(
1072bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFCallback cb) {
1073bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1074bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1075bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1076bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFCallbackForward(handler, camera, cb);
1077bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1078bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1079bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFCallbackForward(
1080bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFCallback cb) {
1081bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1082bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1083bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1084bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1085bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1086bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1087bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocus(final boolean b, Camera camera) {
1088bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1089bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1090bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1091bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocus(b, mCamera);
1092bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1093bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1094bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1095bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1096bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1097bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1098bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ErrorCallback to another thread.
1099bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1100bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ErrorCallbackForward implements Camera.ErrorCallback {
1101bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1102bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1103bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraErrorCallback mCallback;
1104bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1105bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1106bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1107bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1108bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1109bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1110bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1111bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1112bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1113bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1114bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ErrorCallbackForward getNewInstance(
1115bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraErrorCallback cb) {
1116bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1117bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1118bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1119bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ErrorCallbackForward(handler, camera, cb);
1120bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1121bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1122bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ErrorCallbackForward(
1123bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraErrorCallback cb) {
1124bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1125bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1126bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1127bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1128bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1129bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1130bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onError(final int error, Camera camera) {
1131bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1132bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1133bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1134bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onError(error, mCamera);
1135bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1136bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1137bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1138bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1139bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1140bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /** A helper class to forward AutoFocusMoveCallback to another thread. */
1141bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1142bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
1143bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1144bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFMoveCallback mCallback;
1145bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1146bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1147bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1148bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFMoveCallbackForward}.
1149bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1150bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1151bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1152bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1153bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFMoveCallbackForward},
1154bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1155bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1156bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFMoveCallbackForward getNewInstance(
1157bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
1158bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1159bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1160bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1161bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFMoveCallbackForward(handler, camera, cb);
1162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1164bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFMoveCallbackForward(
1165bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
1166bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1167bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1168bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1169bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1170bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocusMoving(
1173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final boolean moving, android.hardware.Camera camera) {
1174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocusMoving(moving, mCamera);
1178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ShutterCallback to to another thread.
1185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ShutterCallbackForward implements ShutterCallback {
1187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraShutterCallback mCallback;
1189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link ShutterCallbackForward}.
1193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link ShutterCallbackForward},
1198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ShutterCallbackForward getNewInstance(
1201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraShutterCallback cb) {
1202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ShutterCallbackForward(handler, camera, cb);
1206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ShutterCallbackForward(
1209bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraShutterCallback cb) {
1210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onShutter() {
1217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onShutter(mCamera);
1221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PictureCallback to another thread.
1228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PictureCallbackForward implements PictureCallback {
1230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPictureCallback mCallback;
1232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PictureCallbackForward}.
1236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PictureCallbackForward},
1241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PictureCallbackForward getNewInstance(
1244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPictureCallback cb) {
1245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PictureCallbackForward(handler, camera, cb);
1249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PictureCallbackForward(
1252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPictureCallback cb) {
1253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPictureTaken(
1260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPictureTaken(data, mCamera);
1265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PreviewCallback to another thread.
1272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PreviewCallbackForward implements PreviewCallback {
1274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPreviewDataCallback mCallback;
1276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PreviewCallbackForward}.
1280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PreviewCallbackForward},
1285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1287bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PreviewCallbackForward getNewInstance(
1288bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
1289bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1290bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1291bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1292bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PreviewCallbackForward(handler, camera, cb);
1293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PreviewCallbackForward(
1296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
1297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewFrame(
1304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1307bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPreviewFrame(data, mCamera);
1309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1310bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1312bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1314bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class FaceDetectionCallbackForward implements FaceDetectionListener {
1315bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraFaceDetectionCallback mCallback;
1317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1318bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1320bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
1321bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1322bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1324bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link FaceDetectionCallbackForward},
1326bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1328bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static FaceDetectionCallbackForward getNewInstance(
1329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
1330bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1332bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new FaceDetectionCallbackForward(handler, camera, cb);
1334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1335bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1336bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private FaceDetectionCallbackForward(
1337bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
1338bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1339bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1340bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1341bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1342bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1343bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1344bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onFaceDetection(
1345bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Camera.Face[] faces, Camera camera) {
1346bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1347bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onFaceDetection(faces, mCamera);
1350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong}
1355