AndroidCameraAgentImpl.java revision 2d01b8e2b5ad30ce3c442799cad4c3d26607fc6f
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;
419d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucherimport java.util.Collections;
429d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucherimport java.util.List;
4301e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kongimport java.util.StringTokenizer;
44bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
45bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong/**
464f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher * A class to implement {@link CameraAgent} of the Android camera framework.
47bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong */
48a0842b40441db5332a5290f941021636b1182761Sol Boucherclass AndroidCameraAgentImpl extends CameraAgent {
49a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static final Log.Tag TAG = new Log.Tag("AndCamAgntImp");
50bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
51b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher    private CameraDeviceInfo.Characteristics mCharacteristics;
528097973089420749dcd1ab4974a629c2466b31ccAngus Kong    private AndroidCameraCapabilities mCapabilities;
53bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
54bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraHandler mCameraHandler;
55bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final HandlerThread mCameraHandlerThread;
56bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final CameraStateHolder mCameraState;
57bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private final DispatchThread mDispatchThread;
582d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    private CameraExceptionHandler mExceptionHandler;
59bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
604f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher    AndroidCameraAgentImpl() {
61bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread = new HandlerThread("Camera Handler Thread");
62bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread.start();
632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        mCameraHandler = new CameraHandler(this, mCameraHandlerThread.getLooper());
642d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        mExceptionHandler = new CameraExceptionHandler(mCameraHandler);
65a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraState = new AndroidCameraStateHolder();
66cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread);
67bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.start();
68bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
69bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
70bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
71bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void recycle() {
7260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        closeCamera(null, true);
73bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.end();
742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        mCameraState.invalidate();
75bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
767e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
777e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    @Override
787e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    public CameraDeviceInfo getCameraDeviceInfo() {
797e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        return AndroidCameraDeviceInfo.create();
807e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
817e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
82a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
83a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected Handler getCameraHandler() {
84a0842b40441db5332a5290f941021636b1182761Sol Boucher        return mCameraHandler;
85a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
86a0842b40441db5332a5290f941021636b1182761Sol Boucher
87a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
88a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected DispatchThread getDispatchThread() {
89a0842b40441db5332a5290f941021636b1182761Sol Boucher        return mDispatchThread;
90a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
91a0842b40441db5332a5290f941021636b1182761Sol Boucher
922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    @Override
932d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    protected CameraStateHolder getCameraState() {
942d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        return mCameraState;
952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    }
962d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    @Override
982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    protected CameraExceptionHandler getCameraExceptionHandler() {
992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        return mExceptionHandler;
1002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    }
1012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
1022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    @Override
1032d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    public void setCameraExceptionHandler(CameraExceptionHandler exceptionHandler) {
1042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        mExceptionHandler = exceptionHandler;
1052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu    }
1062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
1077e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    private static class AndroidCameraDeviceInfo implements CameraDeviceInfo {
1087e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final Camera.CameraInfo[] mCameraInfos;
1097e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mNumberOfCameras;
1107e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstBackCameraId;
1117e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstFrontCameraId;
1127e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1137e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private AndroidCameraDeviceInfo(Camera.CameraInfo[] info, int numberOfCameras,
1147e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                int firstBackCameraId, int firstFrontCameraId) {
1157e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1167e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mCameraInfos = info;
1177e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mNumberOfCameras = numberOfCameras;
1187e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstBackCameraId = firstBackCameraId;
1197e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstFrontCameraId = firstFrontCameraId;
1207e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1217e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1227e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public static AndroidCameraDeviceInfo create() {
1237e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int numberOfCameras;
1247e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            Camera.CameraInfo[] cameraInfos;
1257e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            try {
1267e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                numberOfCameras = Camera.getNumberOfCameras();
1277e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                cameraInfos = new Camera.CameraInfo[numberOfCameras];
1287e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                for (int i = 0; i < numberOfCameras; i++) {
1297e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    cameraInfos[i] = new Camera.CameraInfo();
1307e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    Camera.getCameraInfo(i, cameraInfos[i]);
1317e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1327e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            } catch (RuntimeException ex) {
133eb07f0c4c693566f6f258e84426f518e90513c11Alan Newberger                Log.e(TAG, "Exception while creating CameraDeviceInfo", ex);
1347e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                return null;
1357e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1367e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1377e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstFront = NO_DEVICE;
1387e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstBack = NO_DEVICE;
1397e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            // Get the first (smallest) back and first front camera id.
1407e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            for (int i = numberOfCameras - 1; i >= 0; i--) {
1417e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
1427e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    firstBack = i;
1437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                } else {
1447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
1457e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                        firstFront = i;
1467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    }
1477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1507e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return new AndroidCameraDeviceInfo(cameraInfos, numberOfCameras, firstBack, firstFront);
1517e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1527e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1537e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
154b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        public Characteristics getCharacteristics(int cameraId) {
155b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            Camera.CameraInfo info = mCameraInfos[cameraId];
156b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            if (info != null) {
157b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return new AndroidCharacteristics(info);
158b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            } else {
159b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return null;
160b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
1617e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1627e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1637e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1647e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getNumberOfCameras() {
1657e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mNumberOfCameras;
1667e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1677e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1687e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1697e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstBackCameraId() {
1707e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstBackCameraId;
1717e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1727e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1737e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1747e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstFrontCameraId() {
1757e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstFrontCameraId;
1767e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
177b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
178de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private static class AndroidCharacteristics extends Characteristics {
179b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            private Camera.CameraInfo mCameraInfo;
180b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
181b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            AndroidCharacteristics(Camera.CameraInfo cameraInfo) {
182b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                mCameraInfo = cameraInfo;
183b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
184b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
185b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
186b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public boolean isFacingBack() {
187b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK;
188b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
189b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
190b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
191b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public boolean isFacingFront() {
192b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT;
193b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
194b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
195b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
196b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public int getSensorOrientation() {
197b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.orientation;
198b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
199b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
200b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
201b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public boolean canDisableShutterSound() {
202b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.canDisableShutterSound;
203b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
204b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        }
2057e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
2078447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger    private static class ParametersCache {
2088447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private Parameters mParameters;
2098447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private Camera mCamera;
2108447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
2118447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        public ParametersCache(Camera camera) {
2128447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            mCamera = camera;
2138447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        }
2148447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
2158447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        public synchronized void invalidate() {
2168447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            mParameters = null;
2178447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        }
2188447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
2198447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        /**
2208447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         * Access parameters from the cache. If cache is empty, block by
2218447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         * retrieving parameters directly from Camera, but if cache is present,
2228447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         * returns immediately.
2238447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         */
2248447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        public synchronized Parameters getBlocking() {
2258447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            if (mParameters == null) {
2268447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                mParameters = mCamera.getParameters();
227e4094bd3b85ce20e81a1677319192ed2274d0525Alan Newberger                if (mParameters == null) {
228e4094bd3b85ce20e81a1677319192ed2274d0525Alan Newberger                    Log.e(TAG, "Camera object returned null parameters!");
229e4094bd3b85ce20e81a1677319192ed2274d0525Alan Newberger                    throw new IllegalStateException("camera.getParameters returned null");
230e4094bd3b85ce20e81a1677319192ed2274d0525Alan Newberger                }
2318447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            }
2328447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            return mParameters;
2338447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        }
2348447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger    }
2358447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * The handler on which the actual camera operations happen.
238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
239cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    private class CameraHandler extends HistoryHandler {
2402d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        private CameraAgent mAgent;
241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private Camera mCamera;
24260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        private int mCameraId;
2438447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private ParametersCache mParameterCache;
2446a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin        private int mCancelAfPending = 0;
245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private class CaptureCallbacks {
247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final ShutterCallback mShutter;
248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mRaw;
249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mPostView;
250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mJpeg;
251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            CaptureCallbacks(ShutterCallback shutter, PictureCallback raw, PictureCallback postView,
253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    PictureCallback jpeg) {
254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mShutter = shutter;
255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mRaw = raw;
256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mPostView = postView;
257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJpeg = jpeg;
258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
2612d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        CameraHandler(CameraAgent agent, Looper looper) {
262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            super(looper);
2632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            mAgent = agent;
264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void startFaceDetection() {
267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.startFaceDetection();
268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void stopFaceDetection() {
271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.stopFaceDetection();
272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setFaceDetectionListener(FaceDetectionListener listener) {
275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.setFaceDetectionListener(listener);
276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setPreviewTexture(Object surfaceTexture) {
279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (IOException e) {
282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "Could not set preview texture", e);
283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
287bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void enableShutterSound(boolean enable) {
288bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.enableShutterSound(enable);
289bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
290bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
291bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
292bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setAutoFocusMoveCallback(
293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                android.hardware.Camera camera, Object cb) {
294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException ex) {
297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.w(TAG, ex.getMessage());
298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void requestTakePicture(
302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final ShutterCallback shutter,
303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback raw,
304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback postView,
305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback jpeg) {
306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final CaptureCallbacks callbacks = new CaptureCallbacks(shutter, raw, postView, jpeg);
307cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            obtainMessage(CameraActions.CAPTURE_PHOTO, callbacks).sendToTarget();
308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
310bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * This method does not deal with the API level check.  Everyone should
312bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * check first for supported operations before sending message to this handler.
313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
314bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
315bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void handleMessage(final Message msg) {
316cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            super.handleMessage(msg);
3172d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
3182d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            if (getCameraState().isInvalid()) {
3192d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                Log.v(TAG, "Skip handleMessage - action = '" + CameraActions.stringify(msg.what) + "'");
3202d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                return;
3212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
3226a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            Log.v(TAG, "handleMessage - action = '" + CameraActions.stringify(msg.what) + "'");
3232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
324bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                switch (msg.what) {
326cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.OPEN_CAMERA: {
327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
328bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
329a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_UNOPENED) {
33060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
332bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
33450f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher                        Log.i(TAG, "Opening camera " + cameraId + " with camera1 API");
335bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera = android.hardware.Camera.open(cameraId);
336bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mCamera != null) {
33760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCameraId = cameraId;
3388447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                            mParameterCache = new ParametersCache(mCamera);
339bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
340b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                            mCharacteristics =
341b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                                    AndroidCameraDeviceInfo.create().getCharacteristics(cameraId);
3428447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                            mCapabilities = new AndroidCameraCapabilities(
3438447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                                    mParameterCache.getBlocking());
344bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
345a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
346bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
3472d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                CameraProxy cameraProxy = new AndroidCameraProxyImpl(
3482d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        mAgent, cameraId, mCamera, mCharacteristics, mCapabilities);
3492d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                openCallback.onCameraOpened(cameraProxy);
350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
353b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
356bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
357bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
358bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
359cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RELEASE: {
36060520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        if (mCamera != null) {
36160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera.release();
362a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mCameraState.setState(AndroidCameraStateHolder.CAMERA_UNOPENED);
36360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera = null;
36460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        } else {
36560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            Log.w(TAG, "Releasing camera without any camera opened.");
36660520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        }
367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
368bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
369bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
370cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RECONNECT: {
371bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallbackForward cbForward =
372bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                (CameraOpenCallbackForward) msg.obj;
373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
374bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
375bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.reconnect();
376bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException ex) {
377bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (cbForward != null) {
3782d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                cbForward.onReconnectionFailure(mAgent, generateHistoryString(mCameraId));
379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
380bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
382bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
383a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
384bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
3858097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            cbForward.onCameraOpened(
3862d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                    new AndroidCameraProxyImpl(AndroidCameraAgentImpl.this,
3872d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                            cameraId, mCamera, mCharacteristics, mCapabilities));
388bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
389bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
390bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
391bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
392cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.UNLOCK: {
393bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.unlock();
394a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_UNLOCKED);
395bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
396bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
397bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
398cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.LOCK: {
399bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.lock();
400a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
401bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
402bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
403bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
4042569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // TODO: Lock the CameraSettings object's sizes
405cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: {
406bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setPreviewTexture(msg.obj);
407bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
408bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
409bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
410cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: {
411bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
412bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
413bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException e) {
414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            throw new RuntimeException(e);
415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
416bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
418bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
419cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_PREVIEW_ASYNC: {
420bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraStartPreviewCallbackForward cbForward =
421bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            (CameraStartPreviewCallbackForward) msg.obj;
422bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.startPreview();
423bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
424bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cbForward.onPreviewStarted();
425bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
426bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
427bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
428bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
4292569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // TODO: Unlock the CameraSettings object's sizes
430cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_PREVIEW: {
431bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.stopPreview();
432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
434bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
435cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: {
436bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallbackWithBuffer((PreviewCallback) msg.obj);
437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
438bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
439bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
440cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: {
441bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setOneShotPreviewCallback((PreviewCallback) msg.obj);
442bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
443bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
444bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
445cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ADD_CALLBACK_BUFFER: {
446bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.addCallbackBuffer((byte[]) msg.obj);
447bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
448bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
449bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
450cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.AUTO_FOCUS: {
4516a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        if (mCancelAfPending > 0) {
4526a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                            Log.v(TAG, "handleMessage - Ignored AUTO_FOCUS because there was "
4536a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                                    + mCancelAfPending + " pending CANCEL_AUTO_FOCUS messages");
4546a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                            break; // ignore AF because a CANCEL_AF is queued after this
4556a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        }
456a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_FOCUSING);
457bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.autoFocus((AutoFocusCallback) msg.obj);
458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
459bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
460bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
461cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CANCEL_AUTO_FOCUS: {
4626a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // Ignore all AFs that were already queued until we see
4636a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // a CANCEL_AUTO_FOCUS_FINISH
4646a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        mCancelAfPending++;
465bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.cancelAutoFocus();
466a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
467bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
468bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
469bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
4706a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                    case CameraActions.CANCEL_AUTO_FOCUS_FINISH: {
4716a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // Stop ignoring AUTO_FOCUS messages unless there are additional
4726a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        // CANCEL_AUTO_FOCUSes that were added
4736a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        mCancelAfPending--;
4746a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                        break;
4756a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                    }
4766a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin
477cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: {
478bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setAutoFocusMoveCallback(mCamera, msg.obj);
479bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
480bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
481bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
482cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_DISPLAY_ORIENTATION: {
483de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        // Update preview orientation
484de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mCamera.setDisplayOrientation(
485de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                mCharacteristics.getPreviewOrientation(msg.arg1));
486de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        // Only set the JPEG capture orientation if requested to do so; otherwise,
48725ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        // capture in the sensor's physical orientation. (e.g., JPEG rotation is
48825ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        // necessary in auto-rotate mode.
4898447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
4908447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        parameters.setRotation(
491de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                msg.arg2 > 0 ? mCharacteristics.getJpegOrientation(msg.arg1) : 0);
4928447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mCamera.setParameters(parameters);
49325ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        mParameterCache.invalidate();
49425ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        break;
49525ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                    }
49625ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu
49725ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                    case CameraActions.SET_JPEG_ORIENTATION: {
49825ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        Parameters parameters = mParameterCache.getBlocking();
49925ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        parameters.setRotation(msg.arg1);
50025ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        mCamera.setParameters(parameters);
50125ee73acd2dbd6f60deef5306994fbf3a7997936Senpo Hu                        mParameterCache.invalidate();
502bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
503bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
504bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
505cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ZOOM_CHANGE_LISTENER: {
506bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setZoomChangeListener((OnZoomChangeListener) msg.obj);
507bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
508bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
509bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
510cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_FACE_DETECTION_LISTENER: {
511bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setFaceDetectionListener((FaceDetectionListener) msg.obj);
512bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
513bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
514bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
515cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_FACE_DETECTION: {
516bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        startFaceDetection();
517bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
518bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
519bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
520cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_FACE_DETECTION: {
521bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        stopFaceDetection();
522bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
523bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
524bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
525cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ERROR_CALLBACK: {
526bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setErrorCallback((ErrorCallback) msg.obj);
527bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
528bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
529bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
5308097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    case CameraActions.APPLY_SETTINGS: {
5318447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
5328097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        CameraSettings settings = (CameraSettings) msg.obj;
5338447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        applySettingsToParameters(settings, parameters);
5348447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mCamera.setParameters(parameters);
5358447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mParameterCache.invalidate();
5368097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        break;
5378097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    }
5388097973089420749dcd1ab4974a629c2466b31ccAngus Kong
539cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PARAMETERS: {
5408447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
5418447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        parameters.unflatten((String) msg.obj);
5428447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mCamera.setParameters(parameters);
5438447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mParameterCache.invalidate();
544bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
545bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
546bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
547cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.GET_PARAMETERS: {
5488447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters[] parametersHolder = (Parameters[]) msg.obj;
5498447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
5508447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        parametersHolder[0] = parameters;
551bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
552bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
553bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
554cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK: {
555bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallback((PreviewCallback) msg.obj);
556bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
557bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
558bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
559cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ENABLE_SHUTTER_SOUND: {
560bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        enableShutterSound((msg.arg1 == 1) ? true : false);
561bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
562bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
563bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
564cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.REFRESH_PARAMETERS: {
5658447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mParameterCache.invalidate();;
566bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
567bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
568bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
569cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CAPTURE_PHOTO: {
570a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_CAPTURING);
5712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        CaptureCallbacks captureCallbacks = (CaptureCallbacks) msg.obj;
5722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCamera.takePicture(
5732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                captureCallbacks.mShutter,
5742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                captureCallbacks.mRaw,
5752d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                captureCallbacks.mPostView,
5762d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                captureCallbacks.mJpeg);
577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
578bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
580bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    default: {
5812d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        Log.e(TAG, "Invalid CameraProxy message=" + msg.what);
582bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
583bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
5842d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
5852d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                String cameraAction = CameraActions.stringify(msg.what);
5862d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                int cameraState = mCameraState.getState();
5872d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                String errorContext =
5882d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        "CameraAction[" + cameraAction + "] at CameraState[" + cameraState + "]";
5892d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                Log.e(TAG, "RuntimeException during " + errorContext, ex);
5902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
5912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                // Be conservative by invalidating both CameraAgent and CameraProxy objects.
5922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraState.invalidate();
5932d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
5942d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                if (mCamera != null) {
5952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    Log.i(TAG, "Release camera since mCamera is not null.");
596bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
597bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.release();
5982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    } catch (Exception e) {
5992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        Log.e(TAG, "Fail when calling Camera.release().", e);
6002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    } finally {
6012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCamera = null;
602bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
603bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
6042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
6052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                // Invoke error callback.
6062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                if (msg.what == CameraActions.OPEN_CAMERA && mCamera == null) {
6072d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    final int cameraId = msg.arg1;
6082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    if (msg.obj != null) {
6092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(
6102d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                msg.arg1, generateHistoryString(cameraId));
6112d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
6122d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                } else {
6132d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    mAgent.getCameraExceptionHandler().onCameraException(ex);
614bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
6156a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin            } finally {
6166a9babad6eb8ac3e79a5e036d878ed7408e79f26Igor Murashkin                WaitDoneBundle.unblockSyncWaiters(msg);
617bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
618bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
6198097973089420749dcd1ab4974a629c2466b31ccAngus Kong
6208447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private void applySettingsToParameters(final CameraSettings settings,
6218447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                final Parameters parameters) {
6228097973089420749dcd1ab4974a629c2466b31ccAngus Kong            final CameraCapabilities.Stringifier stringifier = mCapabilities.getStringifier();
6238097973089420749dcd1ab4974a629c2466b31ccAngus Kong            Size photoSize = settings.getCurrentPhotoSize();
6248447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPictureSize(photoSize.width(), photoSize.height());
6258097973089420749dcd1ab4974a629c2466b31ccAngus Kong            Size previewSize = settings.getCurrentPreviewSize();
6268447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPreviewSize(previewSize.width(), previewSize.height());
6278097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getPreviewFrameRate() == -1) {
6288447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setPreviewFpsRange(settings.getPreviewFpsRangeMin(),
6298097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        settings.getPreviewFpsRangeMax());
6308097973089420749dcd1ab4974a629c2466b31ccAngus Kong            } else {
6318447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setPreviewFrameRate(settings.getPreviewFrameRate());
6328097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6338447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPreviewFormat(settings.getCurrentPreviewFormat());
6348447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setJpegQuality(settings.getPhotoJpegCompressionQuality());
6358097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.ZOOM)) {
6369d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                parameters.setZoom(zoomRatioToIndex(settings.getCurrentZoomRatio(),
6379d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        parameters.getZoomRatios()));
6388097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6398447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setExposureCompensation(settings.getExposureCompensationIndex());
6408097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)) {
6418447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setAutoExposureLock(settings.isAutoExposureLocked());
6428097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6438447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setFocusMode(stringifier.stringify(settings.getCurrentFocusMode()));
6448097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK)) {
6458447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setAutoWhiteBalanceLock(settings.isAutoWhiteBalanceLocked());
6468097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6478097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA)) {
648f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getFocusAreas().size() != 0) {
6498447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setFocusAreas(settings.getFocusAreas());
650f73c6cf2f04451ba4517abccd36a114667c69ae3Andy Huibers                } else {
651f73c6cf2f04451ba4517abccd36a114667c69ae3Andy Huibers                    parameters.setFocusAreas(null);
652f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
6538097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6548097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA)) {
655f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getMeteringAreas().size() != 0) {
6568447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setMeteringAreas(settings.getMeteringAreas());
657f73c6cf2f04451ba4517abccd36a114667c69ae3Andy Huibers                } else {
658f73c6cf2f04451ba4517abccd36a114667c69ae3Andy Huibers                    parameters.setMeteringAreas(null);
659f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
6608097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6618097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getCurrentFlashMode() != CameraCapabilities.FlashMode.NO_FLASH) {
6628447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setFlashMode(stringifier.stringify(settings.getCurrentFlashMode()));
6638097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6648097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getCurrentSceneMode() != CameraCapabilities.SceneMode.NO_SCENE_MODE) {
665f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getCurrentSceneMode() != null) {
6668447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters
667f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                            .setSceneMode(stringifier.stringify(settings.getCurrentSceneMode()));
668f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
6698097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6708447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setRecordingHint(settings.isRecordingHintEnabled());
67101e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong            Size jpegThumbSize = settings.getExifThumbnailSize();
6721c1d1afb5701b78fcdf09969bba1c20eb591bccfAlan Newberger            if (jpegThumbSize != null) {
6731c1d1afb5701b78fcdf09969bba1c20eb591bccfAlan Newberger                parameters.setJpegThumbnailSize(jpegThumbSize.width(), jpegThumbSize.height());
6741c1d1afb5701b78fcdf09969bba1c20eb591bccfAlan Newberger            }
6758447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPictureFormat(settings.getCurrentPhotoFormat());
6768097973089420749dcd1ab4974a629c2466b31ccAngus Kong
6778097973089420749dcd1ab4974a629c2466b31ccAngus Kong            CameraSettings.GpsData gpsData = settings.getGpsData();
6788097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (gpsData == null) {
6798447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.removeGpsData();
6808097973089420749dcd1ab4974a629c2466b31ccAngus Kong            } else {
6818447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setGpsTimestamp(gpsData.timeStamp);
6828097973089420749dcd1ab4974a629c2466b31ccAngus Kong                if (gpsData.processingMethod != null) {
6838097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // It's a hack since we always use GPS time stamp but does
6848097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // not use other fields sometimes. Setting processing
6858097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // method to null means the other fields should not be used.
6868447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsAltitude(gpsData.altitude);
6878447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsLatitude(gpsData.latitude);
6888447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsLongitude(gpsData.longitude);
6898447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsProcessingMethod(gpsData.processingMethod);
6908097973089420749dcd1ab4974a629c2466b31ccAngus Kong                }
6918097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6928097973089420749dcd1ab4974a629c2466b31ccAngus Kong
6938097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
6949d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher
6959d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        /**
6969d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         * @param ratio Desired zoom ratio, in [1.0f,+Inf).
6979d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         * @param percentages Available zoom ratios, as percentages.
6989d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         * @return Index of the closest corresponding ratio, rounded up toward
6999d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         *         that of the maximum available ratio.
7009d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         */
7019d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        private int zoomRatioToIndex(float ratio, List<Integer> percentages) {
7029d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            int percent = (int) (ratio * AndroidCameraCapabilities.ZOOM_MULTIPLIER);
7039d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            int index = Collections.binarySearch(percentages, percent);
7049d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            if (index >= 0) {
7059d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                // Found the desired ratio in the supported list
7069d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                return index;
7079d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            } else {
7089d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                // Didn't find an exact match. Where would it have been?
7099d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                index = -(index + 1);
7109d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                if (index == percentages.size()) {
7119d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                    // Put it back in bounds by setting to the maximum allowable zoom
7129d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                    --index;
7139d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                }
7149d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                return index;
7159d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            }
7169d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        }
717bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
718bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
719bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
7204f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher     * A class which implements {@link CameraAgent.CameraProxy} and
721bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera handler thread.
722bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
723a0842b40441db5332a5290f941021636b1182761Sol Boucher    private class AndroidCameraProxyImpl extends CameraAgent.CameraProxy {
7242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        private final CameraAgent mCameraAgent;
725bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final int mCameraId;
726bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /* TODO: remove this Camera instance. */
727bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Camera mCamera;
728b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        private final CameraDeviceInfo.Characteristics mCharacteristics;
729c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private final AndroidCameraCapabilities mCapabilities;
730bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
7312d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        private AndroidCameraProxyImpl(
7322d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                CameraAgent cameraAgent,
7332d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                int cameraId,
7342d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                Camera camera,
735b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                CameraDeviceInfo.Characteristics characteristics,
736c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                AndroidCameraCapabilities capabilities) {
7372d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            mCameraAgent = cameraAgent;
738bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
739bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraId = cameraId;
740b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            mCharacteristics = characteristics;
741c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            mCapabilities = capabilities;
742bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
743bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
7448447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        @Deprecated
745bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
746bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public android.hardware.Camera getCamera() {
7472d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            if (getCameraState().isInvalid()) {
7482d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                return null;
7492d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
750bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCamera;
751bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
752bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
753bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
754bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public int getCameraId() {
755bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCameraId;
756bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
757bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
758bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
759b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        public CameraDeviceInfo.Characteristics getCharacteristics() {
760b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            return mCharacteristics;
761b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        }
762b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
763b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        @Override
764c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        public CameraCapabilities getCapabilities() {
765c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            return new AndroidCameraCapabilities(mCapabilities);
766c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        }
767c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong
768c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        @Override
7692d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        public CameraAgent getAgent() {
7702d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            return mCameraAgent;
7712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        }
7722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu
7732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu        @Override
774bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallback(
775bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
776bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
777bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
778bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
779cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK,
780cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            PreviewCallbackForward.getNewInstance(
781cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
782bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
783bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
784bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
785bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
786a0842b40441db5332a5290f941021636b1182761Sol Boucher
787bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
788bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setOneShotPreviewCallback(final Handler handler,
789bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPreviewDataCallback cb) {
790bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
791bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
792bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
793cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK,
794bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
795bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
796bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
797bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
798bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
799bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
800bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
801bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
802bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallbackWithBuffer(
803bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
804bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
805bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
806bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
807cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER,
808bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
809bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
810bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
811bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
812bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
813bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
814bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
815bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
816bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void autoFocus(final Handler handler, final CameraAFCallback cb) {
817bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final AutoFocusCallback afCallback = new AutoFocusCallback() {
818bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
819bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onAutoFocus(final boolean b, Camera camera) {
820a0842b40441db5332a5290f941021636b1182761Sol Boucher                    if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_FOCUSING) {
821bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.w(TAG, "onAutoFocus callback returning when not focusing");
822bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
823a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
824bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
825bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
826bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
827bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
828bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cb.onAutoFocus(b, AndroidCameraProxyImpl.this);
829bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
830bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
831bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
832bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
833bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
834bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
835bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
8362d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    // Don't bother to wait since camera is in bad state.
8372d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    if (getCameraState().isInvalid()) {
8382d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        return;
8392d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
840a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCameraState.waitForStates(AndroidCameraStateHolder.CAMERA_IDLE);
841cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, afCallback)
842cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
843bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
844bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
845bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
846bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
847bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
848bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
849bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setAutoFocusMoveCallback(
850bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraAFMoveCallback cb) {
8512d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
8522d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
8532d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
8542d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
8552d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK,
8562d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                AFMoveCallbackForward.getNewInstance(
8572d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        handler, AndroidCameraProxyImpl.this, cb))
8582d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
8592d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
8602d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
8612d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
8622d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
8632d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
864bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
865bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
866bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
867bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void takePicture(
868bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraShutterCallback shutter,
869bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback raw, final CameraPictureCallback post,
870bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback jpeg) {
871bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final PictureCallback jpegCallback = new PictureCallback() {
872bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
873bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onPictureTaken(final byte[] data, Camera camera) {
874a0842b40441db5332a5290f941021636b1182761Sol Boucher                    if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_CAPTURING) {
87560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        Log.w(TAG, "picture callback returning when not capturing");
876bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
877a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
878bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
879bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
880bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
881bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
882bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpeg.onPictureTaken(data, AndroidCameraProxyImpl.this);
883bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
884bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
885bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
886bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
887bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
8882d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
8892d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
8902d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
8912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
8922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        // Don't bother to wait since camera is in bad state.
8932d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        if (getCameraState().isInvalid()) {
8942d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                            return;
8952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        }
8962d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraState.waitForStates(AndroidCameraStateHolder.CAMERA_IDLE |
8972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                AndroidCameraStateHolder.CAMERA_UNLOCKED);
8982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.requestTakePicture(ShutterCallbackForward
8992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        .getNewInstance(handler, AndroidCameraProxyImpl.this, shutter),
9002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                PictureCallbackForward
9012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        .getNewInstance(handler, AndroidCameraProxyImpl.this, raw),
9022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                PictureCallbackForward
9032d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        .getNewInstance(handler, AndroidCameraProxyImpl.this, post),
9042d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                jpegCallback
9052d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        );
9062d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
9072d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
9082d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9092d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
9102d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
911bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
912bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
913bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
914bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setZoomChangeListener(final OnZoomChangeListener listener) {
9152d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
9162d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
9172d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9182d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9192d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.SET_ZOOM_CHANGE_LISTENER, listener)
9202d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
9212d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
9222d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
9232d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9242d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
9252d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
926bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
927bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
928bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
929bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setFaceDetectionCallback(final Handler handler,
930bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraFaceDetectionCallback cb) {
9312d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
9322d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
9332d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9342d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9352d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.SET_FACE_DETECTION_LISTENER,
9362d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                FaceDetectionCallbackForward
9372d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
9382d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
9392d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
9402d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
9412d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9422d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
9432d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
944bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
945bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
946bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
947bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setErrorCallback(final Handler handler, final CameraErrorCallback cb) {
9482d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
9492d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
9502d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9512d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9522d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.SET_ERROR_CALLBACK,
9532d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                ErrorCallbackForward.getNewInstance(
9542d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                        handler, AndroidCameraProxyImpl.this, cb))
9552d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
9562d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
9572d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
9582d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9592d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
9602d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
961bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
962bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
9638447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        @Deprecated
964bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
965bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setParameters(final Parameters params) {
966bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (params == null) {
967bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.v(TAG, "null parameters in setParameters()");
968bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return;
969bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
970bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final String flattenedParameters = params.flatten();
9712d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
9722d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJob(new Runnable() {
9732d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9742d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9752d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraState.waitForStates(AndroidCameraStateHolder.CAMERA_IDLE |
9762d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                AndroidCameraStateHolder.CAMERA_UNLOCKED);
9772d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(CameraActions.SET_PARAMETERS, flattenedParameters)
9782d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                .sendToTarget();
9792d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
9802d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                });
9812d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
9822d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
9832d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
984bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
985bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
9868447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        @Deprecated
987bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
988bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Parameters getParameters() {
989bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
9908447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            final Parameters[] parametersHolder = new Parameters[1];
9912d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            try {
9922d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mDispatchThread.runJobSync(new Runnable() {
9932d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    @Override
9942d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    public void run() {
9952d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.obtainMessage(
9962d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                                CameraActions.GET_PARAMETERS, parametersHolder).sendToTarget();
9972d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                        mCameraHandler.post(bundle.mUnlockRunnable);
9982d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                    }
9992d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "get parameters");
10002d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            } catch (final RuntimeException ex) {
10012d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu                mCameraAgent.getCameraExceptionHandler().onDispatchThreadException(ex);
10022d01b8e2b5ad30ce3c442799cad4c3d26607fc6fSenpo Hu            }
10038447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            return parametersHolder[0];
1004bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1005bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1006bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
10078097973089420749dcd1ab4974a629c2466b31ccAngus Kong        public CameraSettings getSettings() {
10088097973089420749dcd1ab4974a629c2466b31ccAngus Kong            return new AndroidCameraSettings(mCapabilities, getParameters());
10098097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
10108097973089420749dcd1ab4974a629c2466b31ccAngus Kong
10118097973089420749dcd1ab4974a629c2466b31ccAngus Kong        @Override
1012a0842b40441db5332a5290f941021636b1182761Sol Boucher        public boolean applySettings(CameraSettings settings) {
1013a0842b40441db5332a5290f941021636b1182761Sol Boucher            return applySettingsHelper(settings, AndroidCameraStateHolder.CAMERA_IDLE |
1014a0842b40441db5332a5290f941021636b1182761Sol Boucher                    AndroidCameraStateHolder.CAMERA_UNLOCKED);
1015bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
101601e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong
101701e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        @Override
101801e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        public String dumpDeviceSettings() {
10198447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            Parameters parameters = getParameters();
10208447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            if (parameters != null) {
10218447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                String flattened = getParameters().flatten();
10228447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
10238447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                String dumpedSettings = new String();
10248447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                while (tokenizer.hasMoreElements()) {
10258447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    dumpedSettings += tokenizer.nextToken() + '\n';
10268447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                }
102701e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong
10288447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                return dumpedSettings;
10298447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            } else {
10308447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                return "[no parameters retrieved]";
10318447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            }
103201e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        }
1033a0842b40441db5332a5290f941021636b1182761Sol Boucher
1034a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1035a0842b40441db5332a5290f941021636b1182761Sol Boucher        public Handler getCameraHandler() {
1036a0842b40441db5332a5290f941021636b1182761Sol Boucher            return AndroidCameraAgentImpl.this.getCameraHandler();
1037a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1038a0842b40441db5332a5290f941021636b1182761Sol Boucher
1039a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1040a0842b40441db5332a5290f941021636b1182761Sol Boucher        public DispatchThread getDispatchThread() {
1041a0842b40441db5332a5290f941021636b1182761Sol Boucher            return AndroidCameraAgentImpl.this.getDispatchThread();
1042a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1043a0842b40441db5332a5290f941021636b1182761Sol Boucher
1044a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
1045a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraStateHolder getCameraState() {
1046a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCameraState;
1047a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1048bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1049bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1050a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static class AndroidCameraStateHolder extends CameraStateHolder {
1051a0842b40441db5332a5290f941021636b1182761Sol Boucher        /* Camera states */
1052a0842b40441db5332a5290f941021636b1182761Sol Boucher        // These states are defined bitwise so we can easily to specify a set of
1053a0842b40441db5332a5290f941021636b1182761Sol Boucher        // states together.
1054a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_UNOPENED = 1;
1055a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_IDLE = 1 << 1;
1056a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_UNLOCKED = 1 << 2;
1057a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_CAPTURING = 1 << 3;
1058a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_FOCUSING = 1 << 4;
1059bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1060a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCameraStateHolder() {
1061a0842b40441db5332a5290f941021636b1182761Sol Boucher            this(CAMERA_UNOPENED);
1062a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
1063a0842b40441db5332a5290f941021636b1182761Sol Boucher
1064a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCameraStateHolder(int state) {
10657e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher            super(state);
1066bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1067bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1068bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1069bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1070bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward AutoFocusCallback to another thread.
1071bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1072bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFCallbackForward implements AutoFocusCallback {
1073bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1074bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1075bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFCallback mCallback;
1076bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1077bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1078bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1079bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1080bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1081bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1082bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1083bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1084bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1085bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1086bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFCallbackForward getNewInstance(
1087bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFCallback cb) {
1088bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1089bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1090bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1091bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFCallbackForward(handler, camera, cb);
1092bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1093bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1094bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFCallbackForward(
1095bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFCallback cb) {
1096bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1097bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1098bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1099bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1100bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1101bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1102bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocus(final boolean b, Camera camera) {
1103bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1104bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1105bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1106bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocus(b, mCamera);
1107bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1108bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1109bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1110bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1111bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1112bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1113bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ErrorCallback to another thread.
1114bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1115bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ErrorCallbackForward implements Camera.ErrorCallback {
1116bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1117bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1118bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraErrorCallback mCallback;
1119bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1120bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1121bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1122bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1123bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1124bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1125bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1126bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1127bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1128bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1129bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ErrorCallbackForward getNewInstance(
1130bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraErrorCallback cb) {
1131bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1132bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1133bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1134bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ErrorCallbackForward(handler, camera, cb);
1135bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1136bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1137bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ErrorCallbackForward(
1138bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraErrorCallback cb) {
1139bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1140bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1141bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1142bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1143bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1144bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1145bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onError(final int error, Camera camera) {
1146bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1147bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1148bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1149bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onError(error, mCamera);
1150bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1151bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1152bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1153bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1154bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1155bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /** A helper class to forward AutoFocusMoveCallback to another thread. */
1156bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1157bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
1158bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1159bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFMoveCallback mCallback;
1160bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1161bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFMoveCallbackForward}.
1164bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1165bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1166bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1167bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1168bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFMoveCallbackForward},
1169bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1170bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFMoveCallbackForward getNewInstance(
1172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
1173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFMoveCallbackForward(handler, camera, cb);
1177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFMoveCallbackForward(
1180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
1181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocusMoving(
1188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final boolean moving, android.hardware.Camera camera) {
1189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocusMoving(moving, mCamera);
1193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ShutterCallback to to another thread.
1200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ShutterCallbackForward implements ShutterCallback {
1202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraShutterCallback mCallback;
1204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link ShutterCallbackForward}.
1208bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1209bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1210bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1211bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1212bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link ShutterCallbackForward},
1213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ShutterCallbackForward getNewInstance(
1216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraShutterCallback cb) {
1217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ShutterCallbackForward(handler, camera, cb);
1221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ShutterCallbackForward(
1224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraShutterCallback cb) {
1225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onShutter() {
1232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onShutter(mCamera);
1236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PictureCallback to another thread.
1243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PictureCallbackForward implements PictureCallback {
1245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPictureCallback mCallback;
1247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PictureCallbackForward}.
1251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PictureCallbackForward},
1256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PictureCallbackForward getNewInstance(
1259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPictureCallback cb) {
1260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PictureCallbackForward(handler, camera, cb);
1264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PictureCallbackForward(
1267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPictureCallback cb) {
1268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPictureTaken(
1275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPictureTaken(data, mCamera);
1280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PreviewCallback to another thread.
1287bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1288bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PreviewCallbackForward implements PreviewCallback {
1289bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1290bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPreviewDataCallback mCallback;
1291bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1292bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PreviewCallbackForward}.
1295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link PreviewCallbackForward},
1300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PreviewCallbackForward getNewInstance(
1303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
1304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1307bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PreviewCallbackForward(handler, camera, cb);
1308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1310bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PreviewCallbackForward(
1311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
1312bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1314bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1315bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1318bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewFrame(
1319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1320bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1321bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1322bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPreviewFrame(data, mCamera);
1324bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1326bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1327bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1328bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class FaceDetectionCallbackForward implements FaceDetectionListener {
1330bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraFaceDetectionCallback mCallback;
1332bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1335bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
1336bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1337bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1338bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1339bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1340bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link FaceDetectionCallbackForward},
1341bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1342bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1343bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static FaceDetectionCallbackForward getNewInstance(
1344bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
1345bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1346bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1347bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new FaceDetectionCallbackForward(handler, camera, cb);
1349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1351bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private FaceDetectionCallbackForward(
1352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
1353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1356bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1357bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1358bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1359bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onFaceDetection(
1360bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Camera.Face[] faces, Camera camera) {
1361bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1362bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1363bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1364bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onFaceDetection(faces, mCamera);
1365bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1366bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1368bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1369bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong}
1370