AndroidCameraAgentImpl.java revision 2569329d6cff25bfe9941df539df14a0aeb4c4f4
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;
58bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
59bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private Handler mCameraExceptionCallbackHandler;
60bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private CameraExceptionCallback mCameraExceptionCallback =
61bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        new CameraExceptionCallback() {
62bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            @Override
63bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public void onCameraException(RuntimeException e) {
64bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
65bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
66bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        };
67bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
684f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher    AndroidCameraAgentImpl() {
69bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread = new HandlerThread("Camera Handler Thread");
70bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandlerThread.start();
71bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraHandler = new CameraHandler(mCameraHandlerThread.getLooper());
72bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mCameraExceptionCallbackHandler = mCameraHandler;
73a0842b40441db5332a5290f941021636b1182761Sol Boucher        mCameraState = new AndroidCameraStateHolder();
74cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher        mDispatchThread = new DispatchThread(mCameraHandler, mCameraHandlerThread);
75bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.start();
76bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
77bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
78bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @Override
79bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void setCameraDefaultExceptionCallback(CameraExceptionCallback callback,
80bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            Handler handler) {
81bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        synchronized (mCameraExceptionCallback) {
82bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallback = callback;
83bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraExceptionCallbackHandler = handler;
84bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
85bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
86bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
8760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong    @Override
88bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    public void recycle() {
8960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        closeCamera(null, true);
90bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        mDispatchThread.end();
91bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
927e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
937e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    @Override
947e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    public CameraDeviceInfo getCameraDeviceInfo() {
957e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        return AndroidCameraDeviceInfo.create();
967e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
977e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
98a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
99a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected Handler getCameraHandler() {
100a0842b40441db5332a5290f941021636b1182761Sol Boucher        return mCameraHandler;
101a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
102a0842b40441db5332a5290f941021636b1182761Sol Boucher
103a0842b40441db5332a5290f941021636b1182761Sol Boucher    @Override
104a0842b40441db5332a5290f941021636b1182761Sol Boucher    protected DispatchThread getDispatchThread() {
105a0842b40441db5332a5290f941021636b1182761Sol Boucher        return mDispatchThread;
106a0842b40441db5332a5290f941021636b1182761Sol Boucher    }
107a0842b40441db5332a5290f941021636b1182761Sol Boucher
1087e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    private static class AndroidCameraDeviceInfo implements CameraDeviceInfo {
1097e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final Camera.CameraInfo[] mCameraInfos;
1107e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mNumberOfCameras;
1117e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstBackCameraId;
1127e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private final int mFirstFrontCameraId;
1137e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1147e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        private AndroidCameraDeviceInfo(Camera.CameraInfo[] info, int numberOfCameras,
1157e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                int firstBackCameraId, int firstFrontCameraId) {
1167e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1177e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mCameraInfos = info;
1187e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mNumberOfCameras = numberOfCameras;
1197e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstBackCameraId = firstBackCameraId;
1207e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            mFirstFrontCameraId = firstFrontCameraId;
1217e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1227e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1237e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public static AndroidCameraDeviceInfo create() {
1247e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int numberOfCameras;
1257e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            Camera.CameraInfo[] cameraInfos;
1267e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            try {
1277e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                numberOfCameras = Camera.getNumberOfCameras();
1287e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                cameraInfos = new Camera.CameraInfo[numberOfCameras];
1297e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                for (int i = 0; i < numberOfCameras; i++) {
1307e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    cameraInfos[i] = new Camera.CameraInfo();
1317e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    Camera.getCameraInfo(i, cameraInfos[i]);
1327e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1337e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            } catch (RuntimeException ex) {
134eb07f0c4c693566f6f258e84426f518e90513c11Alan Newberger                Log.e(TAG, "Exception while creating CameraDeviceInfo", ex);
1357e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                return null;
1367e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1377e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1387e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstFront = NO_DEVICE;
1397e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            int firstBack = NO_DEVICE;
1407e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            // Get the first (smallest) back and first front camera id.
1417e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            for (int i = numberOfCameras - 1; i >= 0; i--) {
1427e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
1437e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    firstBack = i;
1447e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                } else {
1457e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    if (cameraInfos[i].facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
1467e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                        firstFront = i;
1477e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                    }
1487e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong                }
1497e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            }
1507e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1517e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return new AndroidCameraDeviceInfo(cameraInfos, numberOfCameras, firstBack, firstFront);
1527e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1537e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1547e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
155b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        public Characteristics getCharacteristics(int cameraId) {
156b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            Camera.CameraInfo info = mCameraInfos[cameraId];
157b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            if (info != null) {
158b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return new AndroidCharacteristics(info);
159b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            } else {
160b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return null;
161b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
1627e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1637e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1647e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1657e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getNumberOfCameras() {
1667e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mNumberOfCameras;
1677e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1687e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1697e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1707e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstBackCameraId() {
1717e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstBackCameraId;
1727e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
1737e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong
1747e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        @Override
1757e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        public int getFirstFrontCameraId() {
1767e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong            return mFirstFrontCameraId;
1777e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong        }
178b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
179de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher        private static class AndroidCharacteristics extends Characteristics {
180b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            private Camera.CameraInfo mCameraInfo;
181b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
182b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            AndroidCharacteristics(Camera.CameraInfo cameraInfo) {
183b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                mCameraInfo = cameraInfo;
184b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
185b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
186b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
187b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public boolean isFacingBack() {
188b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK;
189b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
190b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
191b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
192b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public boolean isFacingFront() {
193b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT;
194b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
195b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
196b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
197b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public int getSensorOrientation() {
198b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.orientation;
199b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
200b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
201b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            @Override
202b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            public boolean canDisableShutterSound() {
203b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                return mCameraInfo.canDisableShutterSound;
204b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            }
205b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        }
2067e6c76ef7faf26aa1060b4abc1c65934b4e45338Angus Kong    }
207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
2088447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger    private static class ParametersCache {
2098447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private Parameters mParameters;
2108447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private Camera mCamera;
2118447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
2128447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        public ParametersCache(Camera camera) {
2138447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            mCamera = camera;
2148447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        }
2158447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
2168447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        public synchronized void invalidate() {
2178447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            mParameters = null;
2188447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        }
2198447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
2208447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        /**
2218447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         * Access parameters from the cache. If cache is empty, block by
2228447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         * retrieving parameters directly from Camera, but if cache is present,
2238447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         * returns immediately.
2248447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger         */
2258447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        public synchronized Parameters getBlocking() {
2268447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            if (mParameters == null) {
2278447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                mParameters = mCamera.getParameters();
2288447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            }
2298447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            return mParameters;
2308447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        }
2318447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger    }
2328447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger
233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * The handler on which the actual camera operations happen.
235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
236cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher    private class CameraHandler extends HistoryHandler {
237b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong
238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private Camera mCamera;
23960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong        private int mCameraId;
2408447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private ParametersCache mParameterCache;
241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private class CaptureCallbacks {
243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final ShutterCallback mShutter;
244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mRaw;
245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mPostView;
246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            public final PictureCallback mJpeg;
247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            CaptureCallbacks(ShutterCallback shutter, PictureCallback raw, PictureCallback postView,
249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    PictureCallback jpeg) {
250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mShutter = shutter;
251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mRaw = raw;
252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mPostView = postView;
253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mJpeg = jpeg;
254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        CameraHandler(Looper looper) {
258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            super(looper);
259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void startFaceDetection() {
262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.startFaceDetection();
263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void stopFaceDetection() {
266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.stopFaceDetection();
267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setFaceDetectionListener(FaceDetectionListener listener) {
270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.setFaceDetectionListener(listener);
271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setPreviewTexture(Object surfaceTexture) {
274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture);
276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (IOException e) {
277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "Could not set preview texture", e);
278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void enableShutterSound(boolean enable) {
283bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera.enableShutterSound(enable);
284bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
285bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
286bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
287bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void setAutoFocusMoveCallback(
288bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                android.hardware.Camera camera, Object cb) {
289bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
290bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb);
291bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException ex) {
292bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.w(TAG, ex.getMessage());
293bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
294bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
295bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
296bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private void capture(final CaptureCallbacks cb) {
297bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
298bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                mCamera.takePicture(cb.mShutter, cb.mRaw, cb.mPostView, cb.mJpeg);
299bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (RuntimeException e) {
300bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                // TODO: output camera state and focus state for debugging.
301bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.e(TAG, "take picture failed.");
302bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                throw e;
303bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
304bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
305bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
306bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void requestTakePicture(
307bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final ShutterCallback shutter,
308bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback raw,
309bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback postView,
310bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final PictureCallback jpeg) {
311bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final CaptureCallbacks callbacks = new CaptureCallbacks(shutter, raw, postView, jpeg);
312cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            obtainMessage(CameraActions.CAPTURE_PHOTO, callbacks).sendToTarget();
313bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
314bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
315bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
316bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * This method does not deal with the API level check.  Everyone should
317bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * check first for supported operations before sending message to this handler.
318bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
319bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
320bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void handleMessage(final Message msg) {
321cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher            super.handleMessage(msg);
322bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            try {
323bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                switch (msg.what) {
324cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.OPEN_CAMERA: {
325bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallback openCallback = (CameraOpenCallback) msg.obj;
326bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
327a0842b40441db5332a5290f941021636b1182761Sol Boucher                        if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_UNOPENED) {
32860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            openCallback.onDeviceOpenedAlready(cameraId, generateHistoryString(cameraId));
329bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
330bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
331bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
33250f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher                        Log.i(TAG, "Opening camera " + cameraId + " with camera1 API");
333bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera = android.hardware.Camera.open(cameraId);
334bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (mCamera != null) {
33560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCameraId = cameraId;
3368447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                            mParameterCache = new ParametersCache(mCamera);
337bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
338b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                            mCharacteristics =
339b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                                    AndroidCameraDeviceInfo.create().getCharacteristics(cameraId);
3408447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                            mCapabilities = new AndroidCameraCapabilities(
3418447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                                    mParameterCache.getBlocking());
342bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
343a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
344bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
345bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                openCallback.onCameraOpened(
346c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                                        new AndroidCameraProxyImpl(cameraId, mCamera,
347b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                                                mCharacteristics, mCapabilities));
348bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
349bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
350bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (openCallback != null) {
351b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                openCallback.onDeviceOpenFailure(cameraId, generateHistoryString(cameraId));
352bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
353bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
354bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
355bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
356bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
357cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RELEASE: {
35860520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        if (mCamera != null) {
35960520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera.release();
360a0842b40441db5332a5290f941021636b1182761Sol Boucher                            mCameraState.setState(AndroidCameraStateHolder.CAMERA_UNOPENED);
36160520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            mCamera = null;
36260520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        } else {
36360520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                            Log.w(TAG, "Releasing camera without any camera opened.");
36460520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        }
365bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
366bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
367bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
368cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.RECONNECT: {
369bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraOpenCallbackForward cbForward =
370bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                (CameraOpenCallbackForward) msg.obj;
371bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final int cameraId = msg.arg1;
372bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
373bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.reconnect();
374bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException ex) {
375bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (cbForward != null) {
3764f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher                                cbForward.onReconnectionFailure(AndroidCameraAgentImpl.this,
37760520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                                        generateHistoryString(mCameraId));
378bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
379bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            break;
380bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
381bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
382a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
383bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
3848097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            cbForward.onCameraOpened(
385b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                                    new AndroidCameraProxyImpl(cameraId, mCamera, mCharacteristics,
386b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                                            mCapabilities));
387bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
388bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
389bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
390bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
391cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.UNLOCK: {
392bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.unlock();
393a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_UNLOCKED);
394bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
395bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
396bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
397cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.LOCK: {
398bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.lock();
399a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
400bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
401bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
402bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
4032569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // TODO: Lock the CameraSettings object's sizes
404cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_TEXTURE_ASYNC: {
405bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setPreviewTexture(msg.obj);
406bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
407bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
408bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
409cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_DISPLAY_ASYNC: {
410bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        try {
411bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            mCamera.setPreviewDisplay((SurfaceHolder) msg.obj);
412bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } catch (IOException e) {
413bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            throw new RuntimeException(e);
414bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
415bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
416bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
417bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
418cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_PREVIEW_ASYNC: {
419bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        final CameraStartPreviewCallbackForward cbForward =
420bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            (CameraStartPreviewCallbackForward) msg.obj;
421bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.startPreview();
422bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        if (cbForward != null) {
423bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cbForward.onPreviewStarted();
424bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
425bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
426bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
427bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
4282569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher                    // TODO: Unlock the CameraSettings object's sizes
429cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_PREVIEW: {
430bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.stopPreview();
431bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
432bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
433bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
434cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER: {
435bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallbackWithBuffer((PreviewCallback) msg.obj);
436bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
437bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
438bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
439cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK: {
440bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setOneShotPreviewCallback((PreviewCallback) msg.obj);
441bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
442bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
443bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
444cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ADD_CALLBACK_BUFFER: {
445bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.addCallbackBuffer((byte[]) msg.obj);
446bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
447bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
448bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
449cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.AUTO_FOCUS: {
450a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_FOCUSING);
451bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.autoFocus((AutoFocusCallback) msg.obj);
452bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
453bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
454bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
455cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CANCEL_AUTO_FOCUS: {
456bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.cancelAutoFocus();
457a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
458bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
459bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
460bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
461cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK: {
462bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setAutoFocusMoveCallback(mCamera, msg.obj);
463bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
464bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
465bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
466cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_DISPLAY_ORIENTATION: {
467de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        // Update preview orientation
468de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        mCamera.setDisplayOrientation(
469de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                mCharacteristics.getPreviewOrientation(msg.arg1));
470de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        // Only set the JPEG capture orientation if requested to do so; otherwise,
471de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                        // capture in the sensor's physical orientation
4728447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
4738447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        parameters.setRotation(
474de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher                                msg.arg2 > 0 ? mCharacteristics.getJpegOrientation(msg.arg1) : 0);
4758447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mCamera.setParameters(parameters);
476bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
477bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
478bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
479cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ZOOM_CHANGE_LISTENER: {
480bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setZoomChangeListener((OnZoomChangeListener) msg.obj);
481bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
482bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
483bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
484cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_FACE_DETECTION_LISTENER: {
485bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        setFaceDetectionListener((FaceDetectionListener) msg.obj);
486bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
487bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
488bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
489cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.START_FACE_DETECTION: {
490bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        startFaceDetection();
491bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
492bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
493bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
494cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.STOP_FACE_DETECTION: {
495bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        stopFaceDetection();
496bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
497bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
498bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
499cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_ERROR_CALLBACK: {
500bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setErrorCallback((ErrorCallback) msg.obj);
501bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
502bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
503bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
5048097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    case CameraActions.APPLY_SETTINGS: {
5058447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
5068097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        CameraSettings settings = (CameraSettings) msg.obj;
5078447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        applySettingsToParameters(settings, parameters);
5088447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mCamera.setParameters(parameters);
5098447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mParameterCache.invalidate();
5108097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        break;
5118097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    }
5128097973089420749dcd1ab4974a629c2466b31ccAngus Kong
513cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PARAMETERS: {
5148447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
5158447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        parameters.unflatten((String) msg.obj);
5168447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mCamera.setParameters(parameters);
5178447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mParameterCache.invalidate();
518bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
519bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
520bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
521cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.GET_PARAMETERS: {
5228447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters[] parametersHolder = (Parameters[]) msg.obj;
5238447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        Parameters parameters = mParameterCache.getBlocking();
5248447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        parametersHolder[0] = parameters;
525bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
526bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
527bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
528cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.SET_PREVIEW_CALLBACK: {
529bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.setPreviewCallback((PreviewCallback) msg.obj);
530bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
531bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
532bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
533cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.ENABLE_SHUTTER_SOUND: {
534bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        enableShutterSound((msg.arg1 == 1) ? true : false);
535bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
536bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
537bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
538cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.REFRESH_PARAMETERS: {
5398447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                        mParameterCache.invalidate();;
540bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
541bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
542bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
543cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    case CameraActions.CAPTURE_PHOTO: {
544a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_CAPTURING);
545bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        capture((CaptureCallbacks) msg.obj);
546bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        break;
547bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
548bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
549bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    default: {
550bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        throw new RuntimeException("Invalid CameraProxy message=" + msg.what);
551bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
552bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
553bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            } catch (final RuntimeException e) {
554cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                if (msg.what != CameraActions.RELEASE && mCamera != null) {
555bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    try {
556bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        mCamera.release();
557a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_UNOPENED);
558bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } catch (Exception ex) {
559bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.e(TAG, "Fail to release the camera.");
560bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
561bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCamera = null;
562bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                } else {
563bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    if (mCamera == null) {
564cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                        if (msg.what == CameraActions.OPEN_CAMERA) {
565b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                            final int cameraId = msg.arg1;
566bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            if (msg.obj != null) {
567b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                ((CameraOpenCallback) msg.obj).onDeviceOpenFailure(
568b00b7a67213ee6868eb792b2a63ba0dca888a01fAngus Kong                                        msg.arg1, generateHistoryString(cameraId));
569bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
570bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        } else {
571bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            Log.w(TAG, "Cannot handle message " + msg.what + ", mCamera is null.");
572bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
573bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        return;
574bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
575bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
576bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                synchronized (mCameraExceptionCallback) {
577bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraExceptionCallbackHandler.post(new Runnable() {
578bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
579bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
580bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                mCameraExceptionCallback.onCameraException(e);
581bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            }
582bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        });
583bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
584bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
585bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
5868097973089420749dcd1ab4974a629c2466b31ccAngus Kong
5878447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        private void applySettingsToParameters(final CameraSettings settings,
5888447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                final Parameters parameters) {
5898097973089420749dcd1ab4974a629c2466b31ccAngus Kong            final CameraCapabilities.Stringifier stringifier = mCapabilities.getStringifier();
5908097973089420749dcd1ab4974a629c2466b31ccAngus Kong            Size photoSize = settings.getCurrentPhotoSize();
5918447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPictureSize(photoSize.width(), photoSize.height());
5928097973089420749dcd1ab4974a629c2466b31ccAngus Kong            Size previewSize = settings.getCurrentPreviewSize();
5938447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPreviewSize(previewSize.width(), previewSize.height());
5948097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getPreviewFrameRate() == -1) {
5958447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setPreviewFpsRange(settings.getPreviewFpsRangeMin(),
5968097973089420749dcd1ab4974a629c2466b31ccAngus Kong                        settings.getPreviewFpsRangeMax());
5978097973089420749dcd1ab4974a629c2466b31ccAngus Kong            } else {
5988447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setPreviewFrameRate(settings.getPreviewFrameRate());
5998097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6008447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPreviewFormat(settings.getCurrentPreviewFormat());
6018447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setJpegQuality(settings.getPhotoJpegCompressionQuality());
6028097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.ZOOM)) {
6039d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                parameters.setZoom(zoomRatioToIndex(settings.getCurrentZoomRatio(),
6049d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                        parameters.getZoomRatios()));
6058097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6068447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setExposureCompensation(settings.getExposureCompensationIndex());
6078097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_EXPOSURE_LOCK)) {
6088447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setAutoExposureLock(settings.isAutoExposureLocked());
6098097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6108447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setFocusMode(stringifier.stringify(settings.getCurrentFocusMode()));
6118097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.AUTO_WHITE_BALANCE_LOCK)) {
6128447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setAutoWhiteBalanceLock(settings.isAutoWhiteBalanceLocked());
6138097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6148097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.FOCUS_AREA)) {
615f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getFocusAreas().size() != 0) {
6168447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setFocusAreas(settings.getFocusAreas());
617f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
6188097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6198097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (mCapabilities.supports(CameraCapabilities.Feature.METERING_AREA)) {
620f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getMeteringAreas().size() != 0) {
6218447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setMeteringAreas(settings.getMeteringAreas());
622f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
6238097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6248097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getCurrentFlashMode() != CameraCapabilities.FlashMode.NO_FLASH) {
6258447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setFlashMode(stringifier.stringify(settings.getCurrentFlashMode()));
6268097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6278097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (settings.getCurrentSceneMode() != CameraCapabilities.SceneMode.NO_SCENE_MODE) {
628f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                if (settings.getCurrentSceneMode() != null) {
6298447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters
630f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                            .setSceneMode(stringifier.stringify(settings.getCurrentSceneMode()));
631f07afbbde040b9578bc7f188016c3960e8616ab0Angus Kong                }
6328097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6338447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setRecordingHint(settings.isRecordingHintEnabled());
63401e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong            Size jpegThumbSize = settings.getExifThumbnailSize();
6358447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setJpegThumbnailSize(jpegThumbSize.width(), jpegThumbSize.height());
6368447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            parameters.setPictureFormat(settings.getCurrentPhotoFormat());
6378097973089420749dcd1ab4974a629c2466b31ccAngus Kong
6388097973089420749dcd1ab4974a629c2466b31ccAngus Kong            CameraSettings.GpsData gpsData = settings.getGpsData();
6398097973089420749dcd1ab4974a629c2466b31ccAngus Kong            if (gpsData == null) {
6408447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.removeGpsData();
6418097973089420749dcd1ab4974a629c2466b31ccAngus Kong            } else {
6428447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                parameters.setGpsTimestamp(gpsData.timeStamp);
6438097973089420749dcd1ab4974a629c2466b31ccAngus Kong                if (gpsData.processingMethod != null) {
6448097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // It's a hack since we always use GPS time stamp but does
6458097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // not use other fields sometimes. Setting processing
6468097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    // method to null means the other fields should not be used.
6478447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsAltitude(gpsData.altitude);
6488447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsLatitude(gpsData.latitude);
6498447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsLongitude(gpsData.longitude);
6508447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    parameters.setGpsProcessingMethod(gpsData.processingMethod);
6518097973089420749dcd1ab4974a629c2466b31ccAngus Kong                }
6528097973089420749dcd1ab4974a629c2466b31ccAngus Kong            }
6538097973089420749dcd1ab4974a629c2466b31ccAngus Kong
6548097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
6559d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher
6569d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        /**
6579d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         * @param ratio Desired zoom ratio, in [1.0f,+Inf).
6589d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         * @param percentages Available zoom ratios, as percentages.
6599d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         * @return Index of the closest corresponding ratio, rounded up toward
6609d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         *         that of the maximum available ratio.
6619d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher         */
6629d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        private int zoomRatioToIndex(float ratio, List<Integer> percentages) {
6639d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            int percent = (int) (ratio * AndroidCameraCapabilities.ZOOM_MULTIPLIER);
6649d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            int index = Collections.binarySearch(percentages, percent);
6659d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            if (index >= 0) {
6669d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                // Found the desired ratio in the supported list
6679d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                return index;
6689d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            } else {
6699d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                // Didn't find an exact match. Where would it have been?
6709d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                index = -(index + 1);
6719d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                if (index == percentages.size()) {
6729d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                    // Put it back in bounds by setting to the maximum allowable zoom
6739d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                    --index;
6749d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                }
6759d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher                return index;
6769d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher            }
6779d8668449376fa47bc6528c7a61b04d6a0f691b3Sol Boucher        }
678bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
679bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
680bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
6814f425ba476d62b4be7078f2084af37cf306b31c6Sol Boucher     * A class which implements {@link CameraAgent.CameraProxy} and
682bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * camera handler thread.
683bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
684a0842b40441db5332a5290f941021636b1182761Sol Boucher    private class AndroidCameraProxyImpl extends CameraAgent.CameraProxy {
685bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final int mCameraId;
686bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /* TODO: remove this Camera instance. */
687bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Camera mCamera;
688b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        private final CameraDeviceInfo.Characteristics mCharacteristics;
689c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private final AndroidCameraCapabilities mCapabilities;
690bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
691c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        private AndroidCameraProxyImpl(int cameraId, Camera camera,
692b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher                CameraDeviceInfo.Characteristics characteristics,
693c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong                AndroidCameraCapabilities capabilities) {
694bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
695bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCameraId = cameraId;
696b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            mCharacteristics = characteristics;
697c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            mCapabilities = capabilities;
698bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
699bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
7008447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        @Deprecated
701bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
702bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public android.hardware.Camera getCamera() {
703bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCamera;
704bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
705bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
706bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
707bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public int getCameraId() {
708bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return mCameraId;
709bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
710bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
711bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
712b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        public CameraDeviceInfo.Characteristics getCharacteristics() {
713b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher            return mCharacteristics;
714b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        }
715b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher
716b30d2c670f1262f0d60181e40dad33f2151fee4aSol Boucher        @Override
717c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        public CameraCapabilities getCapabilities() {
718c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong            return new AndroidCameraCapabilities(mCapabilities);
719c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        }
720c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong
721c36e3c983c232dc45ed31f3d8e98d8cdd7ac14baAngus Kong        @Override
722bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallback(
723bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
724bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
725bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
726bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
727cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK,
728cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            PreviewCallbackForward.getNewInstance(
729cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
730bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
731bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
732bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
733bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
734a0842b40441db5332a5290f941021636b1182761Sol Boucher
735bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
736bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setOneShotPreviewCallback(final Handler handler,
737bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPreviewDataCallback cb) {
738bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
739bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
740bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
741cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ONE_SHOT_PREVIEW_CALLBACK,
742bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
743bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
744bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
745bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
746bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
747bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
748bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
749bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
750bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setPreviewDataCallbackWithBuffer(
751bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraPreviewDataCallback cb) {
752bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
753bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
754bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
755cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PREVIEW_CALLBACK_WITH_BUFFER,
756bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PreviewCallbackForward
757bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
758bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
759bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
760bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
761bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
762bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
763bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
764bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void autoFocus(final Handler handler, final CameraAFCallback cb) {
765bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final AutoFocusCallback afCallback = new AutoFocusCallback() {
766bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
767bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onAutoFocus(final boolean b, Camera camera) {
768a0842b40441db5332a5290f941021636b1182761Sol Boucher                    if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_FOCUSING) {
769bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        Log.w(TAG, "onAutoFocus callback returning when not focusing");
770bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
771a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
772bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
773bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
774bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
775bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
776bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            cb.onAutoFocus(b, AndroidCameraProxyImpl.this);
777bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
778bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
779bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
780bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
781bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
782bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
783bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
784a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCameraState.waitForStates(AndroidCameraStateHolder.CAMERA_IDLE);
785cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.AUTO_FOCUS, afCallback)
786cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
787bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
788bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
789bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
790bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
791bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
792bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
793bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setAutoFocusMoveCallback(
794bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraAFMoveCallback cb) {
795bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
796bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
797bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
798cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_AUTO_FOCUS_MOVE_CALLBACK,
799cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            AFMoveCallbackForward.getNewInstance(
800cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
801bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
802bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
803bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
804bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
805bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
806bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
807bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void takePicture(
808bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Handler handler, final CameraShutterCallback shutter,
809bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback raw, final CameraPictureCallback post,
810bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraPictureCallback jpeg) {
811bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final PictureCallback jpegCallback = new PictureCallback() {
812bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
813bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void onPictureTaken(final byte[] data, Camera camera) {
814a0842b40441db5332a5290f941021636b1182761Sol Boucher                    if (mCameraState.getState() != AndroidCameraStateHolder.CAMERA_CAPTURING) {
81560520c4df78e595964605cf8acfa21bbafaeba84Angus Kong                        Log.w(TAG, "picture callback returning when not capturing");
816bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    } else {
817a0842b40441db5332a5290f941021636b1182761Sol Boucher                        mCameraState.setState(AndroidCameraStateHolder.CAMERA_IDLE);
818bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    }
819bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    handler.post(new Runnable() {
820bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        @Override
821bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        public void run() {
822bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            jpeg.onPictureTaken(data, AndroidCameraProxyImpl.this);
823bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                        }
824bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    });
825bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
826bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            };
827bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
828bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
829bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
830bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
8317e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher                    mCameraState.waitForStates(AndroidCameraStateHolder.CAMERA_IDLE |
832a0842b40441db5332a5290f941021636b1182761Sol Boucher                            AndroidCameraStateHolder.CAMERA_UNLOCKED);
833bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.requestTakePicture(ShutterCallbackForward
8348097973089420749dcd1ab4974a629c2466b31ccAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, shutter),
835bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
836bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, raw),
837bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            PictureCallbackForward
838bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, post),
8398097973089420749dcd1ab4974a629c2466b31ccAngus Kong                            jpegCallback
8408097973089420749dcd1ab4974a629c2466b31ccAngus Kong                    );
841bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
842bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
843bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
844bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
845bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
846bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setZoomChangeListener(final OnZoomChangeListener listener) {
847bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
848bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
849bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
850cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ZOOM_CHANGE_LISTENER, listener)
851cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
852bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
853bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
854bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
855bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
856bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
857bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setFaceDetectionCallback(final Handler handler,
858bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final CameraFaceDetectionCallback cb) {
859bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
860bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
861bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
862cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_FACE_DETECTION_LISTENER,
863bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            FaceDetectionCallbackForward
864bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                                    .getNewInstance(handler, AndroidCameraProxyImpl.this, cb))
865bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                            .sendToTarget();
866bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
867bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
868bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
869bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
870bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
871bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setErrorCallback(final Handler handler, final CameraErrorCallback cb) {
872bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
873bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
874bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
875cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_ERROR_CALLBACK,
876cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            ErrorCallbackForward.getNewInstance(
877cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                                    handler, AndroidCameraProxyImpl.this, cb))
878cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
879bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
880bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
881bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
882bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
8838447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        @Deprecated
884bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
885bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void setParameters(final Parameters params) {
886bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (params == null) {
887bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Log.v(TAG, "null parameters in setParameters()");
888bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return;
889bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
890bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final String flattenedParameters = params.flatten();
891bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJob(new Runnable() {
892bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
893bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
894a0842b40441db5332a5290f941021636b1182761Sol Boucher                    mCameraState.waitForStates(AndroidCameraStateHolder.CAMERA_IDLE |
895a0842b40441db5332a5290f941021636b1182761Sol Boucher                            AndroidCameraStateHolder.CAMERA_UNLOCKED);
896cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                    mCameraHandler.obtainMessage(CameraActions.SET_PARAMETERS, flattenedParameters)
897cef46862d6937bc98bf1a6b087c5daa22b5239f3Sol Boucher                            .sendToTarget();
898bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
899bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
900bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
901bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
9028447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger        @Deprecated
903bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
904bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public Parameters getParameters() {
905bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            final WaitDoneBundle bundle = new WaitDoneBundle();
9068447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            final Parameters[] parametersHolder = new Parameters[1];
907bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mDispatchThread.runJobSync(new Runnable() {
908bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
909bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
9108447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    Message getParametersMessage = mCameraHandler.obtainMessage(
9118447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                            CameraActions.GET_PARAMETERS, parametersHolder);
9128447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    mCameraHandler.sendMessage(getParametersMessage);
913bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCameraHandler.post(bundle.mUnlockRunnable);
914bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
915bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }, bundle.mWaitLock, CAMERA_OPERATION_TIMEOUT_MS, "get parameters");
9168447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            return parametersHolder[0];
917bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
918bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
919bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
9208097973089420749dcd1ab4974a629c2466b31ccAngus Kong        public CameraSettings getSettings() {
9218097973089420749dcd1ab4974a629c2466b31ccAngus Kong            return new AndroidCameraSettings(mCapabilities, getParameters());
9228097973089420749dcd1ab4974a629c2466b31ccAngus Kong        }
9238097973089420749dcd1ab4974a629c2466b31ccAngus Kong
9248097973089420749dcd1ab4974a629c2466b31ccAngus Kong        @Override
925a0842b40441db5332a5290f941021636b1182761Sol Boucher        public boolean applySettings(CameraSettings settings) {
926a0842b40441db5332a5290f941021636b1182761Sol Boucher            return applySettingsHelper(settings, AndroidCameraStateHolder.CAMERA_IDLE |
927a0842b40441db5332a5290f941021636b1182761Sol Boucher                    AndroidCameraStateHolder.CAMERA_UNLOCKED);
928bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
92901e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong
93001e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        @Override
93101e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        public String dumpDeviceSettings() {
9328447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            Parameters parameters = getParameters();
9338447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            if (parameters != null) {
9348447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                String flattened = getParameters().flatten();
9358447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
9368447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                String dumpedSettings = new String();
9378447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                while (tokenizer.hasMoreElements()) {
9388447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                    dumpedSettings += tokenizer.nextToken() + '\n';
9398447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                }
94001e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong
9418447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                return dumpedSettings;
9428447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            } else {
9438447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger                return "[no parameters retrieved]";
9448447d2276441983d88e8315ffa79a16a90b3d4bbAlan Newberger            }
94501e7c02174ef268b6d6daaa5a5bb4f752d55964cAngus Kong        }
946a0842b40441db5332a5290f941021636b1182761Sol Boucher
947a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
948a0842b40441db5332a5290f941021636b1182761Sol Boucher        public Handler getCameraHandler() {
949a0842b40441db5332a5290f941021636b1182761Sol Boucher            return AndroidCameraAgentImpl.this.getCameraHandler();
950a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
951a0842b40441db5332a5290f941021636b1182761Sol Boucher
952a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
953a0842b40441db5332a5290f941021636b1182761Sol Boucher        public DispatchThread getDispatchThread() {
954a0842b40441db5332a5290f941021636b1182761Sol Boucher            return AndroidCameraAgentImpl.this.getDispatchThread();
955a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
956a0842b40441db5332a5290f941021636b1182761Sol Boucher
957a0842b40441db5332a5290f941021636b1182761Sol Boucher        @Override
958a0842b40441db5332a5290f941021636b1182761Sol Boucher        public CameraStateHolder getCameraState() {
959a0842b40441db5332a5290f941021636b1182761Sol Boucher            return mCameraState;
960a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
961bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
962bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
963a0842b40441db5332a5290f941021636b1182761Sol Boucher    private static class AndroidCameraStateHolder extends CameraStateHolder {
964a0842b40441db5332a5290f941021636b1182761Sol Boucher        /* Camera states */
965a0842b40441db5332a5290f941021636b1182761Sol Boucher        // These states are defined bitwise so we can easily to specify a set of
966a0842b40441db5332a5290f941021636b1182761Sol Boucher        // states together.
967a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_UNOPENED = 1;
968a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_IDLE = 1 << 1;
969a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_UNLOCKED = 1 << 2;
970a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_CAPTURING = 1 << 3;
971a0842b40441db5332a5290f941021636b1182761Sol Boucher        public static final int CAMERA_FOCUSING = 1 << 4;
972bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
973a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCameraStateHolder() {
974a0842b40441db5332a5290f941021636b1182761Sol Boucher            this(CAMERA_UNOPENED);
975a0842b40441db5332a5290f941021636b1182761Sol Boucher        }
976a0842b40441db5332a5290f941021636b1182761Sol Boucher
977a0842b40441db5332a5290f941021636b1182761Sol Boucher        public AndroidCameraStateHolder(int state) {
9787e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher            super(state);
979bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
980bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
981bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
982bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
983bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward AutoFocusCallback to another thread.
984bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
985bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFCallbackForward implements AutoFocusCallback {
986bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
987bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
988bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFCallback mCallback;
989bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
990bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
991bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
992bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
993bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
994bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
995bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
996bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
997bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
998bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
999bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFCallbackForward getNewInstance(
1000bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFCallback cb) {
1001bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1002bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1003bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1004bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFCallbackForward(handler, camera, cb);
1005bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1006bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1007bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFCallbackForward(
1008bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFCallback cb) {
1009bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1010bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1011bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1012bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1013bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1014bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1015bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocus(final boolean b, Camera camera) {
1016bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1017bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1018bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1019bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocus(b, mCamera);
1020bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1021bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1022bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1023bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1024bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1025bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1026bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ErrorCallback to another thread.
1027bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1028bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ErrorCallbackForward implements Camera.ErrorCallback {
1029bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1030bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1031bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraErrorCallback mCallback;
1032bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1033bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1034bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFCallbackForward}.
1035bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1036bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1037bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1038bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1039bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFCallbackForward},
1040bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1041bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1042bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ErrorCallbackForward getNewInstance(
1043bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraErrorCallback cb) {
1044bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1045bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1046bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1047bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ErrorCallbackForward(handler, camera, cb);
1048bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1049bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1050bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ErrorCallbackForward(
1051bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraErrorCallback cb) {
1052bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1053bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1054bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1055bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1056bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1057bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1058bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onError(final int error, Camera camera) {
1059bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1060bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1061bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1062bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onError(error, mCamera);
1063bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1064bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1065bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1066bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1067bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1068bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /** A helper class to forward AutoFocusMoveCallback to another thread. */
1069bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1070bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class AFMoveCallbackForward implements AutoFocusMoveCallback {
1071bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1072bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraAFMoveCallback mCallback;
1073bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1074bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1075bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1076bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link AFMoveCallbackForward}.
1077bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1078bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1079bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1080bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1081bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link AFMoveCallbackForward},
1082bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1083bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1084bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static AFMoveCallbackForward getNewInstance(
1085bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraAFMoveCallback cb) {
1086bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1087bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1088bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1089bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new AFMoveCallbackForward(handler, camera, cb);
1090bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1091bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1092bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private AFMoveCallbackForward(
1093bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraAFMoveCallback cb) {
1094bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1095bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1096bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1097bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1098bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1099bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1100bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onAutoFocusMoving(
1101bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final boolean moving, android.hardware.Camera camera) {
1102bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1103bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1104bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1105bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onAutoFocusMoving(moving, mCamera);
1106bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1107bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1108bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1109bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1110bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1111bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1112bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward ShutterCallback to to another thread.
1113bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1114bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class ShutterCallbackForward implements ShutterCallback {
1115bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1116bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraShutterCallback mCallback;
1117bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1118bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1119bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1120bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link ShutterCallbackForward}.
1121bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1122bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1123bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1124bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1125bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link ShutterCallbackForward},
1126bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1127bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1128bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static ShutterCallbackForward getNewInstance(
1129bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraShutterCallback cb) {
1130bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1131bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1132bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1133bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new ShutterCallbackForward(handler, camera, cb);
1134bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1135bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1136bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private ShutterCallbackForward(
1137bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraShutterCallback cb) {
1138bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1139bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1140bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1141bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1142bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1143bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1144bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onShutter() {
1145bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1146bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1147bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1148bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onShutter(mCamera);
1149bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1150bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1151bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1152bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1153bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1154bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1155bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PictureCallback to another thread.
1156bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1157bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PictureCallbackForward implements PictureCallback {
1158bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1159bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPictureCallback mCallback;
1160bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1161bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1162bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1163bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PictureCallbackForward}.
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 PictureCallbackForward},
1169bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1170bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1171bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PictureCallbackForward getNewInstance(
1172bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPictureCallback cb) {
1173bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1174bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1175bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1176bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PictureCallbackForward(handler, camera, cb);
1177bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1178bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1179bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PictureCallbackForward(
1180bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPictureCallback cb) {
1181bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1182bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1183bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1184bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1185bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1186bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1187bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPictureTaken(
1188bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1189bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1190bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1191bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1192bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPictureTaken(data, mCamera);
1193bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1194bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1195bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1196bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1197bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1198bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    /**
1199bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     * A helper class to forward PreviewCallback to another thread.
1200bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong     */
1201bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class PreviewCallbackForward implements PreviewCallback {
1202bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1203bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraPreviewDataCallback mCallback;
1204bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1205bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1206bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1207bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link PreviewCallbackForward}.
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 PreviewCallbackForward},
1213bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameters is null.
1214bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1215bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static PreviewCallbackForward getNewInstance(
1216bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) {
1217bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1218bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1219bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1220bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new PreviewCallbackForward(handler, camera, cb);
1221bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1222bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1223bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private PreviewCallbackForward(
1224bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraPreviewDataCallback cb) {
1225bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1226bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1227bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1228bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1229bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1230bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1231bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onPreviewFrame(
1232bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final byte[] data, android.hardware.Camera camera) {
1233bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1234bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1235bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1236bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onPreviewFrame(data, mCamera);
1237bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1238bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1239bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1240bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1241bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1242bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    private static class FaceDetectionCallbackForward implements FaceDetectionListener {
1243bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final Handler mHandler;
1244bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraFaceDetectionCallback mCallback;
1245bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private final CameraProxy mCamera;
1246bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1247bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        /**
1248bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * Returns a new instance of {@link FaceDetectionCallbackForward}.
1249bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *
1250bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param handler The handler in which the callback will be invoked in.
1251bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param camera  The {@link CameraProxy} which the callback is from.
1252bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @param cb      The callback to be invoked.
1253bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         * @return        The instance of the {@link FaceDetectionCallbackForward},
1254bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         *                or null if any parameter is null.
1255bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong         */
1256bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public static FaceDetectionCallbackForward getNewInstance(
1257bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) {
1258bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            if (handler == null || camera == null || cb == null) {
1259bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                return null;
1260bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            }
1261bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            return new FaceDetectionCallbackForward(handler, camera, cb);
1262bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1263bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1264bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        private FaceDetectionCallbackForward(
1265bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) {
1266bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler = h;
1267bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCamera = camera;
1268bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mCallback = cb;
1269bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1270bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong
1271bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        @Override
1272bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        public void onFaceDetection(
1273bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                final Camera.Face[] faces, Camera camera) {
1274bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            mHandler.post(new Runnable() {
1275bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                @Override
1276bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                public void run() {
1277bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                    mCallback.onFaceDetection(faces, mCamera);
1278bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong                }
1279bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong            });
1280bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong        }
1281bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong    }
1282bdaaaf5f0257168590fa8965e4d59b054636e6dfAngus Kong}
1283